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