Remove the dependency of libswscale on img_format.h
[ffmpeg.git] / libswscale / yuv2rgb_altivec.c
1 /*
2   marc.hoffman@analog.com    March 8, 2004
3
4   Altivec Acceleration for Color Space Conversion revision 0.2
5
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.
11
12   lots of optimizations to be done here
13
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
16
17   2. the inefficient use of chroma loading needs a bit of brushing up
18
19   3. analysis of pipeline stalls needs to be done, use shark to identify pipeline stalls
20
21
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.
27
28   ADDED altivec_yuv2packedX vertical scl + RGB converter
29
30   March 27,2004
31   PERFORMANCE ANALYSIS
32
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
35
36   720*480*30  ~10MPS
37
38   so we have roughly 10clocks per pixel this is too high something has to be wrong.
39
40   OPTIMIZED clip codes to utilize vec_max and vec_packs removing the need for vec_min.
41
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.
49
50   Now MEMCPY is the largest mips consumer in the system, probably due
51   to the inefficient X11 stuff.
52
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))
57
58   GL2 libraries work now with patch for RGB32
59
60   NOTE quartz vo driver ARGB32_to_RGB24 consumes 30% of the processor
61
62   Integrated luma prescaling adjustment for saturation/contrast/brightness adjustment. 
63
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.
68
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.
73
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
77
78 */
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <inttypes.h>
83 #include <assert.h>
84 #include "config.h"
85 #ifdef HAVE_MALLOC_H
86 #include <malloc.h>
87 #endif
88 #include "rgb2rgb.h"
89 #include "swscale.h"
90 #include "swscale_internal.h"
91
92 #undef PROFILE_THE_BEAST
93 #undef INC_SCALING
94
95 typedef unsigned char ubyte;
96 typedef signed char   sbyte;
97
98
99 /* RGB interleaver, 16 planar pels 8-bit samples per channel in
100    homogeneous vector registers x0,x1,x2 are interleaved with the
101    following technique:
102
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);
109
110   perm_rgb_0:   o0(RG).h v1(B) --> o1*
111               0   1  2   3   4
112              rgbr|gbrg|brgb|rgbr
113              0010 0100 1001 0010
114              0102 3145 2673 894A
115
116   perm_rgb_1:   o0(RG).h v1(B) --> o2
117               0   1  2   3   4
118              gbrg|brgb|bbbb|bbbb
119              0100 1001 1111 1111
120              B5CD 6EF7 89AB CDEF
121
122   perm_rgb_2:   o3(RG).l o2(rgbB.l) --> o4*
123               0   1  2   3   4
124              gbrg|brgb|rgbr|gbrg
125              1111 1111 0010 0100
126              89AB CDEF 0182 3945
127
128   perm_rgb_2:   o3(RG).l o2(rgbB.l) ---> o5*
129               0   1  2   3   4
130              brgb|rgbr|gbrg|brgb
131              1001 0010 0100 1001
132              a67b 89cA BdCD eEFf
133
134 */
135 static
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);
145
146 #define vec_merge3(x2,x1,x0,y0,y1,y2)    \
147 do {                                     \
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);  \
155 } while(0)
156
157 #define vec_mstbgr24(x0,x1,x2,ptr)        \
158 do {                                     \
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++);                 \
164 }  while (0);
165
166 #define vec_mstrgb24(x0,x1,x2,ptr)       \
167 do {                                     \
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++);                 \
173 }  while (0);
174
175 /* pack the pixels in rgb0 format
176    msb R
177    lsb 0
178 */
179 #define vec_mstrgb32(T,x0,x1,x2,x3,ptr)                                                \
180 do {                                                                                   \
181   T _0,_1,_2,_3;                                                                       \
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);                                                         \
194   ptr += 4;                                                                            \
195 }  while (0);
196
197 /*
198
199   | 1     0       1.4021   | | Y |
200   | 1    -0.3441 -0.7142   |x| Cb|
201   | 1     1.7718  0        | | Cr|
202
203
204   Y:      [-128 127]
205   Cb/Cr : [-128 127]
206
207   typical yuv conversion work on Y: 0-255 this version has been optimized for jpeg decode.
208
209 */
210
211
212
213
214 #define vec_unh(x) \
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))
219 #define vec_unl(x) \
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))
224
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 ))
228
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)))
233
234 //#define out_pixels(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,a,a,ptr)
235
236
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)
240 {
241   vector signed   short vx,ux,uvx;
242
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));
248
249   //   ux  = (CBU*(u<<c->CSHIFT)+0x4000)>>15;
250   ux = vec_sl (U, c->CSHIFT);
251   *B = vec_mradds (ux, c->CBU, Y);
252
253   // vx  = (CRV*(v<<c->CSHIFT)+0x4000)>>15;
254   vx = vec_sl (V, c->CSHIFT);
255   *R = vec_mradds (vx, c->CRV, Y);
256
257   // uvx = ((CGU*u) + (CGV*v))>>15;
258   uvx = vec_mradds (U, c->CGU, Y);
259   *G = vec_mradds (V, c->CGV, uvx);
260 }
261
262
263 /*
264   ------------------------------------------------------------------------------
265   CS converters
266   ------------------------------------------------------------------------------
267 */
268
269
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)  \
275 {                                                                          \
276   int w = c->srcW;                                                         \
277   int h = srcSliceH;                                                       \
278   int i,j;                                                                 \
279   int instrides_scl[3];                                                    \
280   vector unsigned char y0,y1;                                              \
281                                                                            \
282   vector signed char  u,v;                                                 \
283                                                                            \
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;                                              \
292                                                                            \
293   vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP;                       \
294   vector unsigned char align_perm;                                         \
295                                                                            \
296   vector signed short                                                      \
297     lCY  = c->CY,                                                          \
298     lOY  = c->OY,                                                          \
299     lCRV = c->CRV,                                                         \
300     lCBU = c->CBU,                                                         \
301     lCGU = c->CGU,                                                         \
302     lCGV = c->CGV;                                                         \
303                                                                            \
304   vector unsigned short lCSHIFT = c->CSHIFT;                               \
305                                                                            \
306   ubyte *y1i   = in[0];                                                    \
307   ubyte *y2i   = in[0]+instrides[0];                                       \
308   ubyte *ui    = in[1];                                                    \
309   ubyte *vi    = in[2];                                                    \
310                                                                            \
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]);                \
317                                                                            \
318                                                                            \
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 */     \
322                                                                            \
323                                                                            \
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);                 \
327                                                                            \
328     for (j=0;j<w/16;j++) {                                                 \
329                                                                            \
330       y1ivP = (vector unsigned char *)y1i;                                 \
331       y2ivP = (vector unsigned char *)y2i;                                 \
332       uivP = (vector unsigned char *)ui;                                   \
333       vivP = (vector unsigned char *)vi;                                   \
334                                                                            \
335       align_perm = vec_lvsl (0, y1i);                                      \
336       y0 = (vector unsigned char)vec_perm (y1ivP[0], y1ivP[1], align_perm);\
337                                                                            \
338       align_perm = vec_lvsl (0, y2i);                                      \
339       y1 = (vector unsigned char)vec_perm (y2ivP[0], y2ivP[1], align_perm);\
340                                                                            \
341       align_perm = vec_lvsl (0, ui);                                       \
342       u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);     \
343                                                                            \
344       align_perm = vec_lvsl (0, vi);                                       \
345       v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);     \
346                                                                            \
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));\
353                                                                            \
354       U  = vec_unpackh (u);                                                \
355       V  = vec_unpackh (v);                                                \
356                                                                            \
357                                                                            \
358         Y0 = vec_unh (y0);                                                 \
359         Y1 = vec_unl (y0);                                                 \
360         Y2 = vec_unh (y1);                                                 \
361         Y3 = vec_unl (y1);                                                 \
362                                                                            \
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);                                    \
367                                                                            \
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);                                         \
373                                                                            \
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);                                         \
379                                                                            \
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);                                       \
385                                                                            \
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);                                             \
392                                                                            \
393         R  = vec_packclp (R0,R1);                                          \
394         G  = vec_packclp (G0,G1);                                          \
395         B  = vec_packclp (B0,B1);                                          \
396                                                                            \
397         out_pixels(R,G,B,oute);                                            \
398                                                                            \
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);                                          \
408                                                                            \
409                                                                            \
410         out_pixels(R,G,B,outo);                                            \
411                                                                            \
412       y1i  += 16;                                                          \
413       y2i  += 16;                                                          \
414       ui   += 8;                                                           \
415       vi   += 8;                                                           \
416                                                                            \
417     }                                                                      \
418                                                                            \
419     outo += (outstrides[0])>>4;                                            \
420     oute += (outstrides[0])>>4;                                            \
421                                                                            \
422     ui    += instrides_scl[1];                                             \
423     vi    += instrides_scl[2];                                             \
424     y1i   += instrides_scl[0];                                             \
425     y2i   += instrides_scl[0];                                             \
426   }                                                                        \
427   return srcSliceH;                                                        \
428 }
429
430
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)
437
438 DEFCSP420_CVT (yuv2_abgr, out_abgr)
439 #if 1
440 DEFCSP420_CVT (yuv2_bgra, out_bgra)
441 #else
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)  
446 {                                                                          
447   int w = c->srcW;                                                         
448   int h = srcSliceH;                                                       
449   int i,j;                                                                 
450   int instrides_scl[3];                                                    
451   vector unsigned char y0,y1;                                              
452                                                                            
453   vector signed char  u,v;                                                 
454                                                                            
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;                                              
463                                                                            
464   vector unsigned char *uivP, *vivP;                                       
465   vector unsigned char align_perm;                                         
466                                                                            
467   vector signed short                                                      
468     lCY  = c->CY,                                                          
469     lOY  = c->OY,                                                          
470     lCRV = c->CRV,                                                         
471     lCBU = c->CBU,                                                         
472     lCGU = c->CGU,                                                         
473     lCGV = c->CGV;                                                         
474                                                                            
475   vector unsigned short lCSHIFT = c->CSHIFT;                               
476                                                                            
477   ubyte *y1i   = in[0];                                                    
478   ubyte *y2i   = in[0]+w;                                                  
479   ubyte *ui    = in[1];                                                    
480   ubyte *vi    = in[2];                                                    
481                                                                            
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]);                
488                                                                            
489                                                                            
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 */     
493                                                                            
494                                                                            
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);                 
498                                                                            
499     for (j=0;j<w/16;j++) {                                                 
500                                                                            
501       y0 = vec_ldl (0,y1i);                                                
502       y1 = vec_ldl (0,y2i);                                                
503       uivP = (vector unsigned char *)ui;                                   
504       vivP = (vector unsigned char *)vi;                                   
505                                                                            
506       align_perm = vec_lvsl (0, ui);                                       
507       u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);     
508                                                                            
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));
514       
515       v  = (vector signed char)
516                 vec_sub (v, (vector signed char)
517                                 vec_splat((vector signed char)AVV(128),0));
518       
519       U  = vec_unpackh (u);                                                
520       V  = vec_unpackh (v);                                                
521                                                                            
522                                                                            
523         Y0 = vec_unh (y0);                                                 
524         Y1 = vec_unl (y0);                                                 
525         Y2 = vec_unh (y1);                                                 
526         Y3 = vec_unl (y1);                                                 
527                                                                            
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);                                    
532                                                                            
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);                                         
538                                                                            
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);
558         
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);
569         
570         out_argb(R,G,B,outo);
571         y1i  += 16;                                                        
572         y2i  += 16;                                                        
573         ui   += 8;
574         vi   += 8;                                                         
575                                                                            
576     }                                                                      
577                                                                            
578     outo += (outstrides[0])>>4;                                            
579     oute += (outstrides[0])>>4;                                            
580                                                                            
581     ui    += instrides_scl[1];                                             
582     vi    += instrides_scl[2];                                             
583     y1i   += instrides_scl[0];                                             
584     y2i   += instrides_scl[0];                                             
585   }                                                                        
586   return srcSliceH;                                                        
587 }
588
589 #endif
590
591
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)
596
597
598 // uyvy|uyvy|uyvy|uyvy
599 // 0123 4567 89ab cdef
600 static
601 const vector unsigned char
602   demux_u = (const vector unsigned char)AVV(0x10,0x00,0x10,0x00,
603                                    0x10,0x04,0x10,0x04,
604                                    0x10,0x08,0x10,0x08,
605                                    0x10,0x0c,0x10,0x0c),
606   demux_v = (const vector unsigned char)AVV(0x10,0x02,0x10,0x02,
607                                    0x10,0x06,0x10,0x06,
608                                    0x10,0x0A,0x10,0x0A,
609                                    0x10,0x0E,0x10,0x0E),
610   demux_y = (const vector unsigned char)AVV(0x10,0x01,0x10,0x03,
611                                    0x10,0x05,0x10,0x07,
612                                    0x10,0x09,0x10,0x0B,
613                                    0x10,0x0D,0x10,0x0F);
614
615 /*
616   this is so I can play live CCIR raw video
617 */
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)
622 {
623   int w = c->srcW;
624   int h = srcSliceH;
625   int i,j;
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;
632   ubyte *img;
633
634   img = in[0];
635   out = (vector unsigned char *)(oplanes[0]+srcSliceY*outstrides[0]);
636
637   for (i=0;i<h;i++) {
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);
642
643       V = (vector signed short)
644         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
645
646       Y = (vector signed short)
647         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
648
649       cvtyuvtoRGB (c, Y,U,V,&R0,&G0,&B0);
650
651       uyvy = vec_ld (16, img);
652       U = (vector signed short)
653         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
654
655       V = (vector signed short)
656         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
657
658       Y = (vector signed short)
659         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
660
661       cvtyuvtoRGB (c, Y,U,V,&R1,&G1,&B1);
662
663       R  = vec_packclp (R0,R1);
664       G  = vec_packclp (G0,G1);
665       B  = vec_packclp (B0,B1);
666
667       //      vec_mstbgr24 (R,G,B, out);
668       out_rgba (R,G,B,out);
669
670       img += 32;
671     }
672   }
673   return srcSliceH;
674 }
675
676
677
678 /* Ok currently the acceleration routine only supports
679    inputs of widths a multiple of 16
680    and heights a multiple 2
681
682    So we just fall back to the C codes for this.
683 */
684 SwsFunc yuv2rgb_init_altivec (SwsContext *c)
685 {
686   if (!(c->flags & SWS_CPU_CAPS_ALTIVEC))    
687     return NULL;
688
689   /*
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.
694     
695   */
696   if ((c->srcW & 0xf) != 0)    return NULL;
697
698   switch (c->srcFormat) {
699   case PIX_FMT_YUV410P:
700   case PIX_FMT_YUV420P:
701   /*case IMGFMT_CLPL:   ??? */
702   case PIX_FMT_GRAY8:
703   case PIX_FMT_NV12:
704   case PIX_FMT_NV21:
705     if ((c->srcH & 0x1) != 0)
706       return NULL;
707
708     switch(c->dstFormat){
709     case PIX_FMT_RGB24:
710       MSG_WARN("ALTIVEC: Color Space RGB24\n");
711       return altivec_yuv2_rgb24;
712     case PIX_FMT_BGR24:
713       MSG_WARN("ALTIVEC: Color Space BGR24\n");
714       return altivec_yuv2_bgr24;
715     case PIX_FMT_ARGB:
716       MSG_WARN("ALTIVEC: Color Space ARGB\n");
717       return altivec_yuv2_argb;
718     case PIX_FMT_ABGR:
719       MSG_WARN("ALTIVEC: Color Space ABGR\n");
720       return altivec_yuv2_abgr;
721     case PIX_FMT_RGBA:
722       MSG_WARN("ALTIVEC: Color Space RGBA\n");
723       return altivec_yuv2_rgba;
724     case PIX_FMT_BGRA:
725       MSG_WARN("ALTIVEC: Color Space BGRA\n");
726       return altivec_yuv2_bgra;
727     default: return NULL;
728     }
729     break;
730
731   case PIX_FMT_UYVY422:
732     switch(c->dstFormat){
733     case PIX_FMT_BGR32:
734       MSG_WARN("ALTIVEC: Color Space UYVY -> RGB32\n");
735       return altivec_uyvy_rgb32;
736     default: return NULL;
737     }
738     break;
739
740   }
741   return NULL;
742 }
743
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;
748         else               return r;
749 }
750
751 void yuv2rgb_altivec_init_tables (SwsContext *c, const int inv_table[4],int brightness,int contrast, int saturation)
752 {
753   union {
754         signed short tmp[8] __attribute__ ((aligned(16)));
755         vector signed short vec;
756         } buf;
757
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
764
765
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);
773 #if 0
774 {
775 int i;
776 char *v[6]={"cy","oy","crv","cbu","cgu","cgv"};
777 for (i=0; i<6;i++)
778   printf("%s %d ", v[i],buf.tmp[i] );
779   printf("\n");
780 }
781 #endif
782  return;
783 }
784
785
786 void
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)
791 {
792   int i,j;
793   short *f;
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;
796
797   vector unsigned char R,G,B,pels[3];
798   vector unsigned char *out,*nout;
799
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)));
803
804   vector signed short *YCoeffs, *CCoeffs;
805
806   YCoeffs = c->vYCoeffsBank+dstY*lumFilterSize;
807   CCoeffs = c->vCCoeffsBank+dstY*chrFilterSize;
808
809   out = (vector unsigned char *)dest;
810
811   for(i=0; i<dstW; i+=16){
812     Y0 = RND;
813     Y1 = RND;
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);
820     }
821
822     U = RND;
823     V = RND;
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);
830     }
831
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);
837
838     Y0 = vec_clip_s16 (Y0);
839     Y1 = vec_clip_s16 (Y1);
840     U  = vec_clip_s16 (U);
841     V  = vec_clip_s16 (V);
842
843     /* now we have
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
846
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
850     */
851
852     U0 = vec_mergeh (U,U);
853     V0 = vec_mergeh (V,V);
854
855     U1 = vec_mergel (U,U);
856     V1 = vec_mergel (V,V);
857
858     cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
859     cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
860
861     R  = vec_packclp (R0,R1);
862     G  = vec_packclp (G0,G1);
863     B  = vec_packclp (B0,B1);
864
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;
872       default:
873         {
874           /* If this is reached, the caller should have called yuv2packedXinC
875              instead. */
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;
881           }
882           return;
883         }
884     }
885   }
886
887   if (i < dstW) {
888     i -= 16;
889
890     Y0 = RND;
891     Y1 = RND;
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);
898     }
899
900     U = RND;
901     V = RND;
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);
908     }
909
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);
915
916     Y0 = vec_clip_s16 (Y0);
917     Y1 = vec_clip_s16 (Y1);
918     U  = vec_clip_s16 (U);
919     V  = vec_clip_s16 (V);
920
921     /* now we have
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
924
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
928     */
929
930     U0 = vec_mergeh (U,U);
931     V0 = vec_mergeh (V,V);
932
933     U1 = vec_mergel (U,U);
934     V1 = vec_mergel (V,V);
935
936     cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
937     cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
938
939     R  = vec_packclp (R0,R1);
940     G  = vec_packclp (G0,G1);
941     B  = vec_packclp (B0,B1);
942
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;
951       default:
952         /* Unreachable, I think. */
953         MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
954                 sws_format_name(c->dstFormat));
955         return;
956     }
957
958     memcpy (&((uint32_t*)dest)[i], scratch, (dstW-i)/4);
959   }
960
961 }