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