ffmpeg: use opt_acodec when setting audio codec in opt_target.
[ffmpeg.git] / libswscale / swscale_template.c
1 /*
2  * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 static inline void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter,
22                               const int16_t **lumSrc, int lumFilterSize,
23                               const int16_t *chrFilter, const int16_t **chrUSrc,
24                               const int16_t **chrVSrc,
25                               int chrFilterSize, const int16_t **alpSrc,
26                               uint8_t *dest, uint8_t *uDest, uint8_t *vDest,
27                               uint8_t *aDest, int dstW, int chrDstW, const uint8_t *lumDither, const uint8_t *chrDither)
28 {
29     yuv2yuvXinC(lumFilter, lumSrc, lumFilterSize,
30                 chrFilter, chrUSrc, chrVSrc, chrFilterSize,
31                 alpSrc, dest, uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
32 }
33
34 static inline void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter,
35                                const int16_t **lumSrc, int lumFilterSize,
36                                const int16_t *chrFilter, const int16_t **chrUSrc,
37                                const int16_t **chrVSrc,
38                                int chrFilterSize, uint8_t *dest, uint8_t *uDest,
39                                int dstW, int chrDstW, enum PixelFormat dstFormat, const uint8_t *dither, const uint8_t *chrDither)
40 {
41     yuv2nv12XinC(lumFilter, lumSrc, lumFilterSize,
42                  chrFilter, chrUSrc, chrVSrc, chrFilterSize,
43                  dest, uDest, dstW, chrDstW, dstFormat, dither, chrDither);
44 }
45
46 static inline void yuv2yuv1_c(SwsContext *c, const int16_t *lumSrc,
47                               const int16_t *chrUSrc, const int16_t *chrVSrc,
48                               const int16_t *alpSrc,
49                               uint8_t *dest, uint8_t *uDest, uint8_t *vDest,
50                               uint8_t *aDest, int dstW, int chrDstW, const uint8_t *lumDither, const uint8_t *chrDither)
51 {
52     int i;
53
54     for (i=0; i<dstW; i++) {
55         int val= (lumSrc[i]+lumDither[i&7])>>7;
56         dest[i]= av_clip_uint8(val);
57     }
58
59     if (uDest)
60         for (i=0; i<chrDstW; i++) {
61             int u=(chrUSrc[i]+chrDither[i&7])>>7;
62             int v=(chrVSrc[i]+chrDither[(i+3)&7])>>7;
63             uDest[i]= av_clip_uint8(u);
64             vDest[i]= av_clip_uint8(v);
65         }
66
67     if (CONFIG_SWSCALE_ALPHA && aDest)
68         for (i=0; i<dstW; i++) {
69             int val= (alpSrc[i]+lumDither[i&7])>>7;
70             aDest[i]= av_clip_uint8(val);
71         }
72 }
73
74
75 /**
76  * vertical scale YV12 to RGB
77  */
78 static inline void yuv2packedX_c(SwsContext *c, const int16_t *lumFilter,
79                                  const int16_t **lumSrc, int lumFilterSize,
80                                  const int16_t *chrFilter, const int16_t **chrUSrc,
81                                  const int16_t **chrVSrc,
82                                  int chrFilterSize, const int16_t **alpSrc,
83                                  uint8_t *dest, int dstW, int dstY)
84 {
85         yuv2packedXinC(c, lumFilter, lumSrc, lumFilterSize,
86                        chrFilter, chrUSrc, chrVSrc, chrFilterSize,
87                        alpSrc, dest, dstW, dstY);
88 }
89
90 /**
91  * vertical bilinear scale YV12 to RGB
92  */
93 static inline void yuv2packed2_c(SwsContext *c, const uint16_t *buf0,
94                                  const uint16_t *buf1, const uint16_t *ubuf0,
95                                  const uint16_t *ubuf1, const uint16_t *vbuf0,
96                                  const uint16_t *vbuf1, const uint16_t *abuf0,
97                                  const uint16_t *abuf1, uint8_t *dest, int dstW,
98                                  int yalpha, int uvalpha, int y)
99 {
100     int  yalpha1=4095- yalpha;
101     int uvalpha1=4095-uvalpha;
102     int i;
103
104     YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB2_C, YSCALE_YUV_2_PACKED2_C(void,0), YSCALE_YUV_2_GRAY16_2_C, YSCALE_YUV_2_MONO2_C)
105 }
106
107 /**
108  * YV12 to RGB without scaling or interpolating
109  */
110 static inline void yuv2packed1_c(SwsContext *c, const uint16_t *buf0,
111                                  const uint16_t *ubuf0, const uint16_t *ubuf1,
112                                  const uint16_t *vbuf0, const uint16_t *vbuf1,
113                                  const uint16_t *abuf0, uint8_t *dest, int dstW,
114                                  int uvalpha, enum PixelFormat dstFormat,
115                                  int flags, int y)
116 {
117     const int yalpha1=0;
118     int i;
119
120     const uint16_t *buf1= buf0; //FIXME needed for RGB1/BGR1
121     const int yalpha= 4096; //FIXME ...
122
123     if (uvalpha < 2048) {
124         YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB1_C, YSCALE_YUV_2_PACKED1_C(void,0), YSCALE_YUV_2_GRAY16_1_C, YSCALE_YUV_2_MONO2_C)
125     } else {
126         YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGB1B_C, YSCALE_YUV_2_PACKED1B_C(void,0), YSCALE_YUV_2_GRAY16_1_C, YSCALE_YUV_2_MONO2_C)
127     }
128 }
129
130 //FIXME yuy2* can read up to 7 samples too much
131
132 static inline void yuy2ToY_c(uint8_t *dst, const uint8_t *src, int width,
133                              uint32_t *unused)
134 {
135     int i;
136     for (i=0; i<width; i++)
137         dst[i]= src[2*i];
138 }
139
140 static inline void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
141                               const uint8_t *src2, int width, uint32_t *unused)
142 {
143     int i;
144     for (i=0; i<width; i++) {
145         dstU[i]= src1[4*i + 1];
146         dstV[i]= src1[4*i + 3];
147     }
148     assert(src1 == src2);
149 }
150
151 static inline void LEToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
152                             const uint8_t *src2, int width, uint32_t *unused)
153 {
154     int i;
155     // FIXME I don't think this code is right for YUV444/422, since then h is not subsampled so
156     // we need to skip each second pixel. Same for BEToUV.
157     for (i=0; i<width; i++) {
158         dstU[i]= src1[2*i + 1];
159         dstV[i]= src2[2*i + 1];
160     }
161 }
162
163 /* This is almost identical to the previous, end exists only because
164  * yuy2ToY/UV)(dst, src+1, ...) would have 100% unaligned accesses. */
165 static inline void uyvyToY_c(uint8_t *dst, const uint8_t *src, int width,
166                              uint32_t *unused)
167 {
168     int i;
169     for (i=0; i<width; i++)
170         dst[i]= src[2*i+1];
171 }
172
173 static inline void uyvyToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
174                               const uint8_t *src2, int width, uint32_t *unused)
175 {
176     int i;
177     for (i=0; i<width; i++) {
178         dstU[i]= src1[4*i + 0];
179         dstV[i]= src1[4*i + 2];
180     }
181     assert(src1 == src2);
182 }
183
184 static inline void BEToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
185                             const uint8_t *src2, int width, uint32_t *unused)
186 {
187     int i;
188     for (i=0; i<width; i++) {
189         dstU[i]= src1[2*i];
190         dstV[i]= src2[2*i];
191     }
192 }
193
194 static inline void nvXXtoUV_c(uint8_t *dst1, uint8_t *dst2,
195                               const uint8_t *src, int width)
196 {
197     int i;
198     for (i = 0; i < width; i++) {
199         dst1[i] = src[2*i+0];
200         dst2[i] = src[2*i+1];
201     }
202 }
203
204 // FIXME Maybe dither instead.
205 #ifndef YUV_NBPS
206 #define YUV_NBPS(depth, endianness, rfunc) \
207 static inline void endianness ## depth ## ToUV_c(uint8_t *dstU, uint8_t *dstV, \
208                                           const uint16_t *srcU, const uint16_t *srcV, \
209                                           int width, uint32_t *unused) \
210 { \
211     int i; \
212     for (i = 0; i < width; i++) { \
213         dstU[i] = rfunc(&srcU[i])>>(depth-8); \
214         dstV[i] = rfunc(&srcV[i])>>(depth-8); \
215     } \
216 } \
217 \
218 static inline void endianness ## depth ## ToY_c(uint8_t *dstY, const uint16_t *srcY, int width, uint32_t *unused) \
219 { \
220     int i; \
221     for (i = 0; i < width; i++) \
222         dstY[i] = rfunc(&srcY[i])>>(depth-8); \
223 } \
224
225 YUV_NBPS( 9, LE, AV_RL16)
226 YUV_NBPS( 9, BE, AV_RB16)
227 YUV_NBPS(10, LE, AV_RL16)
228 YUV_NBPS(10, BE, AV_RB16)
229 #endif // YUV_NBPS
230
231 static inline void nv12ToUV_c(uint8_t *dstU, uint8_t *dstV,
232                               const uint8_t *src1, const uint8_t *src2,
233                               int width, uint32_t *unused)
234 {
235     nvXXtoUV_c(dstU, dstV, src1, width);
236 }
237
238 static inline void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV,
239                               const uint8_t *src1, const uint8_t *src2,
240                               int width, uint32_t *unused)
241 {
242     nvXXtoUV_c(dstV, dstU, src1, width);
243 }
244
245 static inline void bgr24ToY_c(int16_t *dst, const uint8_t *src,
246                               int width, uint32_t *unused)
247 {
248     int i;
249     for (i=0; i<width; i++) {
250         int b= src[i*3+0];
251         int g= src[i*3+1];
252         int r= src[i*3+2];
253
254         dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
255     }
256 }
257
258 static inline void bgr24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
259                                const uint8_t *src2, int width, uint32_t *unused)
260 {
261     int i;
262     for (i=0; i<width; i++) {
263         int b= src1[3*i + 0];
264         int g= src1[3*i + 1];
265         int r= src1[3*i + 2];
266
267         dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
268         dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
269     }
270     assert(src1 == src2);
271 }
272
273 static inline void bgr24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
274                                     const uint8_t *src2, int width, uint32_t *unused)
275 {
276     int i;
277     for (i=0; i<width; i++) {
278         int b= src1[6*i + 0] + src1[6*i + 3];
279         int g= src1[6*i + 1] + src1[6*i + 4];
280         int r= src1[6*i + 2] + src1[6*i + 5];
281
282         dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
283         dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
284     }
285     assert(src1 == src2);
286 }
287
288 static inline void rgb24ToY_c(int16_t *dst, const uint8_t *src, int width,
289                               uint32_t *unused)
290 {
291     int i;
292     for (i=0; i<width; i++) {
293         int r= src[i*3+0];
294         int g= src[i*3+1];
295         int b= src[i*3+2];
296
297         dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
298     }
299 }
300
301 static inline void rgb24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
302                                const uint8_t *src2, int width, uint32_t *unused)
303 {
304     int i;
305     assert(src1==src2);
306     for (i=0; i<width; i++) {
307         int r= src1[3*i + 0];
308         int g= src1[3*i + 1];
309         int b= src1[3*i + 2];
310
311         dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
312         dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
313     }
314 }
315
316 static inline void rgb24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
317                                     const uint8_t *src2, int width, uint32_t *unused)
318 {
319     int i;
320     assert(src1==src2);
321     for (i=0; i<width; i++) {
322         int r= src1[6*i + 0] + src1[6*i + 3];
323         int g= src1[6*i + 1] + src1[6*i + 4];
324         int b= src1[6*i + 2] + src1[6*i + 5];
325
326         dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
327         dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
328     }
329 }
330
331
332 // bilinear / bicubic scaling
333 static inline void hScale_c(int16_t *dst, int dstW, const uint8_t *src,
334                             int srcW, int xInc,
335                             const int16_t *filter, const int16_t *filterPos,
336                             int filterSize)
337 {
338     int i;
339     for (i=0; i<dstW; i++) {
340         int j;
341         int srcPos= filterPos[i];
342         int val=0;
343         for (j=0; j<filterSize; j++) {
344             val += ((int)src[srcPos + j])*filter[filterSize*i + j];
345         }
346         //filter += hFilterSize;
347         dst[i] = FFMIN(val>>7, (1<<15)-1); // the cubic equation does overflow ...
348         //dst[i] = val>>7;
349     }
350 }
351
352 static inline void hScale16_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
353                                     const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
354 {
355     int i, j;
356
357     for (i=0; i<dstW; i++) {
358         int srcPos= filterPos[i];
359         int val=0;
360         for (j=0; j<filterSize; j++) {
361             val += ((int)src[srcPos + j])*filter[filterSize*i + j];
362         }
363         dst[i] = FFMIN(val>>shift, (1<<15)-1); // the cubic equation does overflow ...
364     }
365 }
366
367 static inline void hScale16X_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
368                                     const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
369 {
370     int i, j;
371     for (i=0; i<dstW; i++) {
372         int srcPos= filterPos[i];
373         int val=0;
374         for (j=0; j<filterSize; j++) {
375             val += ((int)av_bswap16(src[srcPos + j]))*filter[filterSize*i + j];
376         }
377         dst[i] = FFMIN(val>>shift, (1<<15)-1); // the cubic equation does overflow ...
378     }
379 }
380
381 //FIXME all pal and rgb srcFormats could do this convertion as well
382 //FIXME all scalers more complex than bilinear could do half of this transform
383 static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
384 {
385     int i;
386     for (i = 0; i < width; i++) {
387         dstU[i] = (FFMIN(dstU[i],30775)*4663 - 9289992)>>12; //-264
388         dstV[i] = (FFMIN(dstV[i],30775)*4663 - 9289992)>>12; //-264
389     }
390 }
391 static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
392 {
393     int i;
394     for (i = 0; i < width; i++) {
395         dstU[i] = (dstU[i]*1799 + 4081085)>>11; //1469
396         dstV[i] = (dstV[i]*1799 + 4081085)>>11; //1469
397     }
398 }
399 static void lumRangeToJpeg_c(int16_t *dst, int width)
400 {
401     int i;
402     for (i = 0; i < width; i++)
403         dst[i] = (FFMIN(dst[i],30189)*19077 - 39057361)>>14;
404 }
405 static void lumRangeFromJpeg_c(int16_t *dst, int width)
406 {
407     int i;
408     for (i = 0; i < width; i++)
409         dst[i] = (dst[i]*14071 + 33561947)>>14;
410 }
411
412 static inline void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
413                                   const uint8_t *src, int srcW, int xInc)
414 {
415     int i;
416     unsigned int xpos=0;
417     for (i=0;i<dstWidth;i++) {
418         register unsigned int xx=xpos>>16;
419         register unsigned int xalpha=(xpos&0xFFFF)>>9;
420         dst[i]= (src[xx]<<7) + (src[xx+1] - src[xx])*xalpha;
421         xpos+=xInc;
422     }
423     for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)
424         dst[i] = src[srcW-1]*128;
425 }
426
427       // *** horizontal scale Y line to temp buffer
428 static inline void hyscale_c(SwsContext *c, uint16_t *dst, int dstWidth,
429                              const uint8_t *src, int srcW, int xInc,
430                              const int16_t *hLumFilter,
431                              const int16_t *hLumFilterPos, int hLumFilterSize,
432                              uint8_t *formatConvBuffer,
433                              uint32_t *pal, int isAlpha)
434 {
435     void (*toYV12)(uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12;
436     void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
437
438     src += isAlpha ? c->alpSrcOffset : c->lumSrcOffset;
439
440     if (toYV12) {
441         toYV12(formatConvBuffer, src, srcW, pal);
442         src= formatConvBuffer;
443     }
444
445     if (c->hScale16) {
446         int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
447         c->hScale16(dst, dstWidth, (const uint16_t*)src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize, shift);
448     } else if (!c->hyscale_fast) {
449         c->hScale(dst, dstWidth, src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize);
450     } else { // fast bilinear upscale / crap downscale
451         c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
452     }
453
454     if (convertRange)
455         convertRange(dst, dstWidth);
456 }
457
458 static inline void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2,
459                                   int dstWidth, const uint8_t *src1,
460                                   const uint8_t *src2, int srcW, int xInc)
461 {
462     int i;
463     unsigned int xpos=0;
464     for (i=0;i<dstWidth;i++) {
465         register unsigned int xx=xpos>>16;
466         register unsigned int xalpha=(xpos&0xFFFF)>>9;
467         dst1[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha);
468         dst2[i]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);
469         xpos+=xInc;
470     }
471     for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--) {
472         dst1[i] = src1[srcW-1]*128;
473         dst2[i] = src2[srcW-1]*128;
474     }
475 }
476
477 inline static void hcscale_c(SwsContext *c, uint16_t *dst1, uint16_t *dst2, int dstWidth,
478                              const uint8_t *src1, const uint8_t *src2,
479                              int srcW, int xInc, const int16_t *hChrFilter,
480                              const int16_t *hChrFilterPos, int hChrFilterSize,
481                              uint8_t *formatConvBuffer, uint32_t *pal)
482 {
483
484     src1 += c->chrSrcOffset;
485     src2 += c->chrSrcOffset;
486
487     if (c->chrToYV12) {
488         uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW*2+78, 16);
489         c->chrToYV12(formatConvBuffer, buf2, src1, src2, srcW, pal);
490         src1= formatConvBuffer;
491         src2= buf2;
492     }
493
494     if (c->hScale16) {
495         int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
496         c->hScale16(dst1, dstWidth, (const uint16_t*)src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
497         c->hScale16(dst2, dstWidth, (const uint16_t*)src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
498     } else if (!c->hcscale_fast) {
499         c->hScale(dst1, dstWidth, src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);
500         c->hScale(dst2, dstWidth, src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize);
501     } else { // fast bilinear upscale / crap downscale
502         c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
503     }
504
505     if (c->chrConvertRange)
506         c->chrConvertRange(dst1, dst2, dstWidth);
507 }
508
509 #define DEBUG_SWSCALE_BUFFERS 0
510 #define DEBUG_BUFFERS(...) if (DEBUG_SWSCALE_BUFFERS) av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
511
512 #if HAVE_MMX
513 static void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufIndex,
514                                   int lastInLumBuf, int lastInChrBuf);
515 #endif
516
517 static int swScale_c(SwsContext *c, const uint8_t* src[], int srcStride[],
518                      int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
519 {
520     /* load a few things into local vars to make the code more readable? and faster */
521     const int srcW= c->srcW;
522     const int dstW= c->dstW;
523     const int dstH= c->dstH;
524     const int chrDstW= c->chrDstW;
525     const int chrSrcW= c->chrSrcW;
526     const int lumXInc= c->lumXInc;
527     const int chrXInc= c->chrXInc;
528     const enum PixelFormat dstFormat= c->dstFormat;
529     const int flags= c->flags;
530     int16_t *vLumFilterPos= c->vLumFilterPos;
531     int16_t *vChrFilterPos= c->vChrFilterPos;
532     int16_t *hLumFilterPos= c->hLumFilterPos;
533     int16_t *hChrFilterPos= c->hChrFilterPos;
534     int16_t *vLumFilter= c->vLumFilter;
535     int16_t *vChrFilter= c->vChrFilter;
536     int16_t *hLumFilter= c->hLumFilter;
537     int16_t *hChrFilter= c->hChrFilter;
538     int32_t *lumMmxFilter= c->lumMmxFilter;
539     int32_t *chrMmxFilter= c->chrMmxFilter;
540     int32_t av_unused *alpMmxFilter= c->alpMmxFilter;
541     const int vLumFilterSize= c->vLumFilterSize;
542     const int vChrFilterSize= c->vChrFilterSize;
543     const int hLumFilterSize= c->hLumFilterSize;
544     const int hChrFilterSize= c->hChrFilterSize;
545     int16_t **lumPixBuf= c->lumPixBuf;
546     int16_t **chrUPixBuf= c->chrUPixBuf;
547     int16_t **chrVPixBuf= c->chrVPixBuf;
548     int16_t **alpPixBuf= c->alpPixBuf;
549     const int vLumBufSize= c->vLumBufSize;
550     const int vChrBufSize= c->vChrBufSize;
551     uint8_t *formatConvBuffer= c->formatConvBuffer;
552     const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample;
553     const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);
554     int lastDstY;
555     uint32_t *pal=c->pal_yuv;
556
557     /* vars which will change and which we need to store back in the context */
558     int dstY= c->dstY;
559     int lumBufIndex= c->lumBufIndex;
560     int chrBufIndex= c->chrBufIndex;
561     int lastInLumBuf= c->lastInLumBuf;
562     int lastInChrBuf= c->lastInChrBuf;
563
564     if (isPacked(c->srcFormat)) {
565         src[0]=
566         src[1]=
567         src[2]=
568         src[3]= src[0];
569         srcStride[0]=
570         srcStride[1]=
571         srcStride[2]=
572         srcStride[3]= srcStride[0];
573     }
574     srcStride[1]<<= c->vChrDrop;
575     srcStride[2]<<= c->vChrDrop;
576
577     DEBUG_BUFFERS("swScale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
578                   src[0], srcStride[0], src[1], srcStride[1], src[2], srcStride[2], src[3], srcStride[3],
579                   dst[0], dstStride[0], dst[1], dstStride[1], dst[2], dstStride[2], dst[3], dstStride[3]);
580     DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
581                    srcSliceY,    srcSliceH,    dstY,    dstH);
582     DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",
583                    vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);
584
585     if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) {
586         static int warnedAlready=0; //FIXME move this into the context perhaps
587         if (flags & SWS_PRINT_INFO && !warnedAlready) {
588             av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n"
589                    "         ->cannot do aligned memory accesses anymore\n");
590             warnedAlready=1;
591         }
592     }
593
594     /* Note the user might start scaling the picture in the middle so this
595        will not get executed. This is not really intended but works
596        currently, so people might do it. */
597     if (srcSliceY ==0) {
598         lumBufIndex=-1;
599         chrBufIndex=-1;
600         dstY=0;
601         lastInLumBuf= -1;
602         lastInChrBuf= -1;
603     }
604
605     lastDstY= dstY;
606
607     for (;dstY < dstH; dstY++) {
608         unsigned char *dest =dst[0]+dstStride[0]*dstY;
609         const int chrDstY= dstY>>c->chrDstVSubSample;
610         unsigned char *uDest=dst[1]+dstStride[1]*chrDstY;
611         unsigned char *vDest=dst[2]+dstStride[2]*chrDstY;
612         unsigned char *aDest=(CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3]+dstStride[3]*dstY : NULL;
613         const uint8_t *lumDither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat) ? dithers[7][dstY   &7] : flat64;
614         const uint8_t *chrDither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat) ? dithers[7][chrDstY&7] : flat64;
615
616         const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
617         const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<<c->chrDstVSubSample) - 1), dstH-1)];
618         const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input
619         int lastLumSrcY= firstLumSrcY + vLumFilterSize -1; // Last line needed as input
620         int lastLumSrcY2=firstLumSrcY2+ vLumFilterSize -1; // Last line needed as input
621         int lastChrSrcY= firstChrSrcY + vChrFilterSize -1; // Last line needed as input
622         int enough_lines;
623
624         //handle holes (FAST_BILINEAR & weird filters)
625         if (firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1;
626         if (firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1;
627         assert(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);
628         assert(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);
629
630         DEBUG_BUFFERS("dstY: %d\n", dstY);
631         DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
632                          firstLumSrcY,    lastLumSrcY,    lastInLumBuf);
633         DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
634                          firstChrSrcY,    lastChrSrcY,    lastInChrBuf);
635
636         // Do we have enough lines in this slice to output the dstY line
637         enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample);
638
639         if (!enough_lines) {
640             lastLumSrcY = srcSliceY + srcSliceH - 1;
641             lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
642             DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
643                                             lastLumSrcY, lastChrSrcY);
644         }
645
646         //Do horizontal scaling
647         while(lastInLumBuf < lastLumSrcY) {
648             const uint8_t *src1= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];
649             const uint8_t *src2= src[3]+(lastInLumBuf + 1 - srcSliceY)*srcStride[3];
650             lumBufIndex++;
651             assert(lumBufIndex < 2*vLumBufSize);
652             assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);
653             assert(lastInLumBuf + 1 - srcSliceY >= 0);
654             hyscale_c(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc,
655                       hLumFilter, hLumFilterPos, hLumFilterSize,
656                       formatConvBuffer,
657                       pal, 0);
658             if (CONFIG_SWSCALE_ALPHA && alpPixBuf)
659                 hyscale_c(c, alpPixBuf[ lumBufIndex ], dstW, src2, srcW,
660                           lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize,
661                           formatConvBuffer,
662                           pal, 1);
663             lastInLumBuf++;
664             DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n",
665                                lumBufIndex,    lastInLumBuf);
666         }
667         while(lastInChrBuf < lastChrSrcY) {
668             const uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];
669             const uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];
670             chrBufIndex++;
671             assert(chrBufIndex < 2*vChrBufSize);
672             assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));
673             assert(lastInChrBuf + 1 - chrSrcSliceY >= 0);
674             //FIXME replace parameters through context struct (some at least)
675
676             if (c->needs_hcscale)
677                 hcscale_c(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex],
678                           chrDstW, src1, src2, chrSrcW, chrXInc,
679                           hChrFilter, hChrFilterPos, hChrFilterSize,
680                           formatConvBuffer, pal);
681             lastInChrBuf++;
682             DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",
683                                chrBufIndex,    lastInChrBuf);
684         }
685         //wrap buf index around to stay inside the ring buffer
686         if (lumBufIndex >= vLumBufSize) lumBufIndex-= vLumBufSize;
687         if (chrBufIndex >= vChrBufSize) chrBufIndex-= vChrBufSize;
688         if (!enough_lines)
689             break; //we can't output a dstY line so let's try with the next slice
690
691 #if HAVE_MMX
692         updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, lastInLumBuf, lastInChrBuf);
693 #endif
694         if (dstY < dstH-2) {
695             const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
696             const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
697             const int16_t **chrVSrcPtr= (const int16_t **) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
698             const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
699             if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {
700                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
701                 if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi
702                 c->yuv2nv12X(c,
703                              vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
704                              vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
705                              dest, uDest, dstW, chrDstW, dstFormat, lumDither, chrDither);
706             } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12 like
707                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
708                 if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
709                 if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
710                     yuv2yuvX16inC(vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
711                                   vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr,
712                                   chrVSrcPtr, vChrFilterSize,
713                                   alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest,
714                                   (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,
715                                   dstFormat);
716                 } else if (vLumFilterSize == 1 && vChrFilterSize == 1) { // unscaled YV12
717                     const int16_t *lumBuf = lumSrcPtr[0];
718                     const int16_t *chrUBuf= chrUSrcPtr[0];
719                     const int16_t *chrVBuf= chrVSrcPtr[0];
720                     const int16_t *alpBuf= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? alpSrcPtr[0] : NULL;
721                     c->yuv2yuv1(c, lumBuf, chrUBuf, chrVBuf, alpBuf, dest,
722                                 uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
723                 } else { //General YV12
724                     c->yuv2yuvX(c,
725                                 vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
726                                 vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr,
727                                 chrVSrcPtr, vChrFilterSize,
728                                 alpSrcPtr, dest, uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
729                 }
730             } else {
731                 assert(lumSrcPtr  + vLumFilterSize - 1 < lumPixBuf  + vLumBufSize*2);
732                 assert(chrUSrcPtr + vChrFilterSize - 1 < chrUPixBuf + vChrBufSize*2);
733                 if (vLumFilterSize == 1 && vChrFilterSize == 2) { //unscaled RGB
734                     int chrAlpha= vChrFilter[2*dstY+1];
735                     if(flags & SWS_FULL_CHR_H_INT) {
736                         yuv2rgbXinC_full(c, //FIXME write a packed1_full function
737                                          vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
738                                          vChrFilter+dstY*vChrFilterSize, chrUSrcPtr,
739                                          chrVSrcPtr, vChrFilterSize,
740                                          alpSrcPtr, dest, dstW, dstY);
741                     } else {
742                         c->yuv2packed1(c, *lumSrcPtr, *chrUSrcPtr, *(chrUSrcPtr+1),
743                                        *chrVSrcPtr, *(chrVSrcPtr+1),
744                                        alpPixBuf ? *alpSrcPtr : NULL,
745                                        dest, dstW, chrAlpha, dstFormat, flags, dstY);
746                     }
747                 } else if (vLumFilterSize == 2 && vChrFilterSize == 2) { //bilinear upscale RGB
748                     int lumAlpha= vLumFilter[2*dstY+1];
749                     int chrAlpha= vChrFilter[2*dstY+1];
750                     lumMmxFilter[2]=
751                     lumMmxFilter[3]= vLumFilter[2*dstY   ]*0x10001;
752                     chrMmxFilter[2]=
753                     chrMmxFilter[3]= vChrFilter[2*chrDstY]*0x10001;
754                     if(flags & SWS_FULL_CHR_H_INT) {
755                         yuv2rgbXinC_full(c, //FIXME write a packed2_full function
756                                          vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
757                                          vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
758                                          alpSrcPtr, dest, dstW, dstY);
759                     } else {
760                         c->yuv2packed2(c, *lumSrcPtr, *(lumSrcPtr+1), *chrUSrcPtr, *(chrUSrcPtr+1),
761                                        *chrVSrcPtr, *(chrVSrcPtr+1),
762                                        alpPixBuf ? *alpSrcPtr : NULL, alpPixBuf ? *(alpSrcPtr+1) : NULL,
763                                        dest, dstW, lumAlpha, chrAlpha, dstY);
764                     }
765                 } else { //general RGB
766                     if(flags & SWS_FULL_CHR_H_INT) {
767                         yuv2rgbXinC_full(c,
768                                          vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
769                                          vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
770                                          alpSrcPtr, dest, dstW, dstY);
771                     } else {
772                         c->yuv2packedX(c,
773                                        vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
774                                        vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
775                                        alpSrcPtr, dest, dstW, dstY);
776                     }
777                 }
778             }
779         } else { // hmm looks like we can't use MMX here without overwriting this array's tail
780             const int16_t **lumSrcPtr= (const int16_t **)lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
781             const int16_t **chrUSrcPtr= (const int16_t **)chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
782             const int16_t **chrVSrcPtr= (const int16_t **)chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
783             const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **)alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
784             if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {
785                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
786                 if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi
787                 yuv2nv12XinC(
788                              vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
789                              vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
790                              dest, uDest, dstW, chrDstW, dstFormat, lumDither, chrDither);
791             } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12
792                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
793                 if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
794                 if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
795                     yuv2yuvX16inC(
796                                   vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
797                                   vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
798                                   alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest, (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,
799                                   dstFormat);
800                 } else {
801                     yuv2yuvXinC(
802                                 vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,
803                                 vChrFilter+chrDstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
804                                 alpSrcPtr, dest, uDest, vDest, aDest, dstW, chrDstW, lumDither, chrDither);
805                 }
806             } else {
807                 assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);
808                 assert(chrUSrcPtr + vChrFilterSize - 1 < chrUPixBuf + vChrBufSize*2);
809                 if(flags & SWS_FULL_CHR_H_INT) {
810                     yuv2rgbXinC_full(c,
811                                      vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
812                                      vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
813                                      alpSrcPtr, dest, dstW, dstY);
814                 } else {
815                     yuv2packedXinC(c,
816                                    vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
817                                    vChrFilter+dstY*vChrFilterSize, chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
818                                    alpSrcPtr, dest, dstW, dstY);
819                 }
820             }
821         }
822     }
823
824     if ((dstFormat == PIX_FMT_YUVA420P) && !alpPixBuf)
825         fillPlane(dst[3], dstStride[3], dstW, dstY-lastDstY, lastDstY, 255);
826
827 #if HAVE_MMX2
828     if (av_get_cpu_flags() & AV_CPU_FLAG_MMX2)
829         __asm__ volatile("sfence":::"memory");
830 #endif
831     emms_c();
832
833     /* store changed local vars back in the context */
834     c->dstY= dstY;
835     c->lumBufIndex= lumBufIndex;
836     c->chrBufIndex= chrBufIndex;
837     c->lastInLumBuf= lastInLumBuf;
838     c->lastInChrBuf= lastInChrBuf;
839
840     return dstY - lastDstY;
841 }
842
843 static void sws_init_swScale_c(SwsContext *c)
844 {
845     enum PixelFormat srcFormat = c->srcFormat;
846
847     c->yuv2nv12X    = yuv2nv12X_c;
848     c->yuv2yuv1     = yuv2yuv1_c;
849     c->yuv2yuvX     = yuv2yuvX_c;
850     c->yuv2packed1  = yuv2packed1_c;
851     c->yuv2packed2  = yuv2packed2_c;
852     c->yuv2packedX  = yuv2packedX_c;
853
854     c->hScale       = hScale_c;
855
856     if (c->flags & SWS_FAST_BILINEAR)
857     {
858         c->hyscale_fast = hyscale_fast_c;
859         c->hcscale_fast = hcscale_fast_c;
860     }
861
862     c->chrToYV12 = NULL;
863     switch(srcFormat) {
864         case PIX_FMT_YUYV422  : c->chrToYV12 = yuy2ToUV_c; break;
865         case PIX_FMT_UYVY422  : c->chrToYV12 = uyvyToUV_c; break;
866         case PIX_FMT_NV12     : c->chrToYV12 = nv12ToUV_c; break;
867         case PIX_FMT_NV21     : c->chrToYV12 = nv21ToUV_c; break;
868         case PIX_FMT_RGB8     :
869         case PIX_FMT_BGR8     :
870         case PIX_FMT_PAL8     :
871         case PIX_FMT_BGR4_BYTE:
872         case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV; break;
873         case PIX_FMT_GRAY16BE :
874         case PIX_FMT_YUV420P9BE:
875         case PIX_FMT_YUV422P10BE:
876         case PIX_FMT_YUV420P10BE:
877         case PIX_FMT_YUV420P16BE:
878         case PIX_FMT_YUV422P16BE:
879         case PIX_FMT_YUV444P16BE: c->hScale16= HAVE_BIGENDIAN ? hScale16_c : hScale16X_c; break;
880         case PIX_FMT_GRAY16LE :
881         case PIX_FMT_YUV420P9LE:
882         case PIX_FMT_YUV422P10LE:
883         case PIX_FMT_YUV420P10LE:
884         case PIX_FMT_YUV420P16LE:
885         case PIX_FMT_YUV422P16LE:
886         case PIX_FMT_YUV444P16LE: c->hScale16= HAVE_BIGENDIAN ? hScale16X_c : hScale16_c; break;
887     }
888     if (c->chrSrcHSubSample) {
889         switch(srcFormat) {
890         case PIX_FMT_RGB48BE: c->chrToYV12 = rgb48BEToUV_half; break;
891         case PIX_FMT_RGB48LE: c->chrToYV12 = rgb48LEToUV_half; break;
892         case PIX_FMT_BGR48BE: c->chrToYV12 = bgr48BEToUV_half; break;
893         case PIX_FMT_BGR48LE: c->chrToYV12 = bgr48LEToUV_half; break;
894         case PIX_FMT_RGB32  : c->chrToYV12 = bgr32ToUV_half;  break;
895         case PIX_FMT_RGB32_1: c->chrToYV12 = bgr321ToUV_half; break;
896         case PIX_FMT_BGR24  : c->chrToYV12 = bgr24ToUV_half_c; break;
897         case PIX_FMT_BGR565 : c->chrToYV12 = bgr16ToUV_half; break;
898         case PIX_FMT_BGR555 : c->chrToYV12 = bgr15ToUV_half; break;
899         case PIX_FMT_BGR32  : c->chrToYV12 = rgb32ToUV_half;  break;
900         case PIX_FMT_BGR32_1: c->chrToYV12 = rgb321ToUV_half; break;
901         case PIX_FMT_RGB24  : c->chrToYV12 = rgb24ToUV_half_c; break;
902         case PIX_FMT_RGB565 : c->chrToYV12 = rgb16ToUV_half; break;
903         case PIX_FMT_RGB555 : c->chrToYV12 = rgb15ToUV_half; break;
904         }
905     } else {
906         switch(srcFormat) {
907         case PIX_FMT_RGB48BE: c->chrToYV12 = rgb48BEToUV; break;
908         case PIX_FMT_RGB48LE: c->chrToYV12 = rgb48LEToUV; break;
909         case PIX_FMT_BGR48BE: c->chrToYV12 = bgr48BEToUV; break;
910         case PIX_FMT_BGR48LE: c->chrToYV12 = bgr48LEToUV; break;
911         case PIX_FMT_RGB32  : c->chrToYV12 = bgr32ToUV;  break;
912         case PIX_FMT_RGB32_1: c->chrToYV12 = bgr321ToUV; break;
913         case PIX_FMT_BGR24  : c->chrToYV12 = bgr24ToUV_c; break;
914         case PIX_FMT_BGR565 : c->chrToYV12 = bgr16ToUV; break;
915         case PIX_FMT_BGR555 : c->chrToYV12 = bgr15ToUV; break;
916         case PIX_FMT_BGR32  : c->chrToYV12 = rgb32ToUV;  break;
917         case PIX_FMT_BGR32_1: c->chrToYV12 = rgb321ToUV; break;
918         case PIX_FMT_RGB24  : c->chrToYV12 = rgb24ToUV_c; break;
919         case PIX_FMT_RGB565 : c->chrToYV12 = rgb16ToUV; break;
920         case PIX_FMT_RGB555 : c->chrToYV12 = rgb15ToUV; break;
921         }
922     }
923
924     c->lumToYV12 = NULL;
925     c->alpToYV12 = NULL;
926     switch (srcFormat) {
927     case PIX_FMT_YUYV422  :
928     case PIX_FMT_GRAY8A   :
929                             c->lumToYV12 = yuy2ToY_c; break;
930     case PIX_FMT_UYVY422  :
931                             c->lumToYV12 = uyvyToY_c; break;
932     case PIX_FMT_BGR24    : c->lumToYV12 = bgr24ToY_c; break;
933     case PIX_FMT_BGR565   : c->lumToYV12 = bgr16ToY; break;
934     case PIX_FMT_BGR555   : c->lumToYV12 = bgr15ToY; break;
935     case PIX_FMT_RGB24    : c->lumToYV12 = rgb24ToY_c; break;
936     case PIX_FMT_RGB565   : c->lumToYV12 = rgb16ToY; break;
937     case PIX_FMT_RGB555   : c->lumToYV12 = rgb15ToY; break;
938     case PIX_FMT_RGB8     :
939     case PIX_FMT_BGR8     :
940     case PIX_FMT_PAL8     :
941     case PIX_FMT_BGR4_BYTE:
942     case PIX_FMT_RGB4_BYTE: c->lumToYV12 = palToY; break;
943     case PIX_FMT_MONOBLACK: c->lumToYV12 = monoblack2Y; break;
944     case PIX_FMT_MONOWHITE: c->lumToYV12 = monowhite2Y; break;
945     case PIX_FMT_RGB32  : c->lumToYV12 = bgr32ToY;  break;
946     case PIX_FMT_RGB32_1: c->lumToYV12 = bgr321ToY; break;
947     case PIX_FMT_BGR32  : c->lumToYV12 = rgb32ToY;  break;
948     case PIX_FMT_BGR32_1: c->lumToYV12 = rgb321ToY; break;
949     case PIX_FMT_RGB48BE: c->lumToYV12 = rgb48BEToY; break;
950     case PIX_FMT_RGB48LE: c->lumToYV12 = rgb48LEToY; break;
951     case PIX_FMT_BGR48BE: c->lumToYV12 = bgr48BEToY; break;
952     case PIX_FMT_BGR48LE: c->lumToYV12 = bgr48LEToY; break;
953     }
954     if (c->alpPixBuf) {
955         switch (srcFormat) {
956         case PIX_FMT_RGB32  :
957         case PIX_FMT_RGB32_1:
958         case PIX_FMT_BGR32  :
959         case PIX_FMT_BGR32_1: c->alpToYV12 = abgrToA; break;
960         case PIX_FMT_GRAY8A : c->alpToYV12 = yuy2ToY_c; break;
961         case PIX_FMT_PAL8   : c->alpToYV12 = palToA; break;
962         }
963     }
964
965     if(isAnyRGB(c->srcFormat) || c->srcFormat == PIX_FMT_PAL8)
966         c->hScale16= hScale16_c;
967
968     switch (srcFormat) {
969     case PIX_FMT_GRAY8A :
970         c->alpSrcOffset = 1;
971         break;
972     case PIX_FMT_RGB32  :
973     case PIX_FMT_BGR32  :
974         c->alpSrcOffset = 3;
975         break;
976     }
977
978     if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
979         if (c->srcRange) {
980             c->lumConvertRange = lumRangeFromJpeg_c;
981             c->chrConvertRange = chrRangeFromJpeg_c;
982         } else {
983             c->lumConvertRange = lumRangeToJpeg_c;
984             c->chrConvertRange = chrRangeToJpeg_c;
985         }
986     }
987
988     if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
989           srcFormat == PIX_FMT_MONOBLACK || srcFormat == PIX_FMT_MONOWHITE))
990         c->needs_hcscale = 1;
991 }