Browse code

swscale: split swscale.c in unscaled and generic conversion routines.

This duplicates the function fillPlane().

Ronald S. Bultje authored on 2011/06/03 14:45:16
Showing 4 changed files
... ...
@@ -5,7 +5,8 @@ FFLIBS = avutil
5 5
 
6 6
 HEADERS = swscale.h
7 7
 
8
-OBJS = options.o rgb2rgb.o swscale.o utils.o yuv2rgb.o
8
+OBJS = options.o rgb2rgb.o swscale.o utils.o yuv2rgb.o \
9
+       swscale_unscaled.o
9 10
 
10 11
 OBJS-$(ARCH_BFIN)          +=  bfin/internal_bfin.o     \
11 12
                                bfin/swscale_bfin.o      \
... ...
@@ -69,14 +69,6 @@ untested special converters
69 69
 
70 70
 #define DITHER1XBPP
71 71
 
72
-#define isPacked(x)         (       \
73
-           (x)==PIX_FMT_PAL8        \
74
-        || (x)==PIX_FMT_YUYV422     \
75
-        || (x)==PIX_FMT_UYVY422     \
76
-        || (x)==PIX_FMT_Y400A       \
77
-        || isAnyRGB(x)              \
78
-    )
79
-
80 72
 #define RGB2YUV_SHIFT 15
81 73
 #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
82 74
 #define BV (-(int)(0.081*224/255*(1<<RGB2YUV_SHIFT)+0.5))
... ...
@@ -2096,834 +2088,3 @@ SwsFunc ff_getSwsFunc(SwsContext *c)
2096 2096
 
2097 2097
     return swScale;
2098 2098
 }
2099
-
2100
-static void copyPlane(const uint8_t *src, int srcStride,
2101
-                      int srcSliceY, int srcSliceH, int width,
2102
-                      uint8_t *dst, int dstStride)
2103
-{
2104
-    dst += dstStride * srcSliceY;
2105
-    if (dstStride == srcStride && srcStride > 0) {
2106
-        memcpy(dst, src, srcSliceH * dstStride);
2107
-    } else {
2108
-        int i;
2109
-        for (i=0; i<srcSliceH; i++) {
2110
-            memcpy(dst, src, width);
2111
-            src += srcStride;
2112
-            dst += dstStride;
2113
-        }
2114
-    }
2115
-}
2116
-
2117
-static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2118
-                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
2119
-{
2120
-    uint8_t *dst = dstParam[1] + dstStride[1]*srcSliceY/2;
2121
-
2122
-    copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
2123
-              dstParam[0], dstStride[0]);
2124
-
2125
-    if (c->dstFormat == PIX_FMT_NV12)
2126
-        interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]);
2127
-    else
2128
-        interleaveBytes(src[2], src[1], dst, c->srcW/2, srcSliceH/2, srcStride[2], srcStride[1], dstStride[0]);
2129
-
2130
-    return srcSliceH;
2131
-}
2132
-
2133
-static int planarToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2134
-                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
2135
-{
2136
-    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
2137
-
2138
-    yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
2139
-
2140
-    return srcSliceH;
2141
-}
2142
-
2143
-static int planarToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2144
-                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
2145
-{
2146
-    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
2147
-
2148
-    yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
2149
-
2150
-    return srcSliceH;
2151
-}
2152
-
2153
-static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2154
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
2155
-{
2156
-    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
2157
-
2158
-    yuv422ptoyuy2(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
2159
-
2160
-    return srcSliceH;
2161
-}
2162
-
2163
-static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2164
-                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
2165
-{
2166
-    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
2167
-
2168
-    yuv422ptouyvy(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
2169
-
2170
-    return srcSliceH;
2171
-}
2172
-
2173
-static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2174
-                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
2175
-{
2176
-    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
2177
-    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
2178
-    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
2179
-
2180
-    yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
2181
-
2182
-    if (dstParam[3])
2183
-        fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
2184
-
2185
-    return srcSliceH;
2186
-}
2187
-
2188
-static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2189
-                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
2190
-{
2191
-    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
2192
-    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
2193
-    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
2194
-
2195
-    yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
2196
-
2197
-    return srcSliceH;
2198
-}
2199
-
2200
-static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2201
-                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
2202
-{
2203
-    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
2204
-    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
2205
-    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
2206
-
2207
-    uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
2208
-
2209
-    if (dstParam[3])
2210
-        fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
2211
-
2212
-    return srcSliceH;
2213
-}
2214
-
2215
-static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2216
-                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
2217
-{
2218
-    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
2219
-    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
2220
-    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
2221
-
2222
-    uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
2223
-
2224
-    return srcSliceH;
2225
-}
2226
-
2227
-static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
2228
-{
2229
-    int i;
2230
-    for (i=0; i<num_pixels; i++)
2231
-        ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | (src[(i<<1)+1] << 24);
2232
-}
2233
-
2234
-static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
2235
-{
2236
-    int i;
2237
-
2238
-    for (i=0; i<num_pixels; i++)
2239
-        ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | src[(i<<1)+1];
2240
-}
2241
-
2242
-static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
2243
-{
2244
-    int i;
2245
-
2246
-    for (i=0; i<num_pixels; i++) {
2247
-        //FIXME slow?
2248
-        dst[0]= palette[src[i<<1]*4+0];
2249
-        dst[1]= palette[src[i<<1]*4+1];
2250
-        dst[2]= palette[src[i<<1]*4+2];
2251
-        dst+= 3;
2252
-    }
2253
-}
2254
-
2255
-static int palToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2256
-                           int srcSliceH, uint8_t* dst[], int dstStride[])
2257
-{
2258
-    const enum PixelFormat srcFormat= c->srcFormat;
2259
-    const enum PixelFormat dstFormat= c->dstFormat;
2260
-    void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
2261
-                 const uint8_t *palette)=NULL;
2262
-    int i;
2263
-    uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
2264
-    const uint8_t *srcPtr= src[0];
2265
-
2266
-    if (srcFormat == PIX_FMT_Y400A) {
2267
-        switch (dstFormat) {
2268
-        case PIX_FMT_RGB32  : conv = gray8aToPacked32; break;
2269
-        case PIX_FMT_BGR32  : conv = gray8aToPacked32; break;
2270
-        case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
2271
-        case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
2272
-        case PIX_FMT_RGB24  : conv = gray8aToPacked24; break;
2273
-        case PIX_FMT_BGR24  : conv = gray8aToPacked24; break;
2274
-        }
2275
-    } else if (usePal(srcFormat)) {
2276
-        switch (dstFormat) {
2277
-        case PIX_FMT_RGB32  : conv = sws_convertPalette8ToPacked32; break;
2278
-        case PIX_FMT_BGR32  : conv = sws_convertPalette8ToPacked32; break;
2279
-        case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
2280
-        case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
2281
-        case PIX_FMT_RGB24  : conv = sws_convertPalette8ToPacked24; break;
2282
-        case PIX_FMT_BGR24  : conv = sws_convertPalette8ToPacked24; break;
2283
-        }
2284
-    }
2285
-
2286
-    if (!conv)
2287
-        av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
2288
-               sws_format_name(srcFormat), sws_format_name(dstFormat));
2289
-    else {
2290
-        for (i=0; i<srcSliceH; i++) {
2291
-            conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
2292
-            srcPtr+= srcStride[0];
2293
-            dstPtr+= dstStride[0];
2294
-        }
2295
-    }
2296
-
2297
-    return srcSliceH;
2298
-}
2299
-
2300
-#define isRGBA32(x) (            \
2301
-           (x) == PIX_FMT_ARGB   \
2302
-        || (x) == PIX_FMT_RGBA   \
2303
-        || (x) == PIX_FMT_BGRA   \
2304
-        || (x) == PIX_FMT_ABGR   \
2305
-        )
2306
-
2307
-/* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
2308
-static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2309
-                           int srcSliceH, uint8_t* dst[], int dstStride[])
2310
-{
2311
-    const enum PixelFormat srcFormat= c->srcFormat;
2312
-    const enum PixelFormat dstFormat= c->dstFormat;
2313
-    const int srcBpp= (c->srcFormatBpp + 7) >> 3;
2314
-    const int dstBpp= (c->dstFormatBpp + 7) >> 3;
2315
-    const int srcId= c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */
2316
-    const int dstId= c->dstFormatBpp >> 2;
2317
-    void (*conv)(const uint8_t *src, uint8_t *dst, int src_size)=NULL;
2318
-
2319
-#define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst)
2320
-
2321
-    if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
2322
-        if (     CONV_IS(ABGR, RGBA)
2323
-              || CONV_IS(ARGB, BGRA)
2324
-              || CONV_IS(BGRA, ARGB)
2325
-              || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
2326
-        else if (CONV_IS(ABGR, ARGB)
2327
-              || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
2328
-        else if (CONV_IS(ABGR, BGRA)
2329
-              || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
2330
-        else if (CONV_IS(BGRA, RGBA)
2331
-              || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
2332
-        else if (CONV_IS(BGRA, ABGR)
2333
-              || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
2334
-    } else
2335
-    /* BGR -> BGR */
2336
-    if (  (isBGRinInt(srcFormat) && isBGRinInt(dstFormat))
2337
-       || (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
2338
-        switch(srcId | (dstId<<4)) {
2339
-        case 0x34: conv= rgb16to15; break;
2340
-        case 0x36: conv= rgb24to15; break;
2341
-        case 0x38: conv= rgb32to15; break;
2342
-        case 0x43: conv= rgb15to16; break;
2343
-        case 0x46: conv= rgb24to16; break;
2344
-        case 0x48: conv= rgb32to16; break;
2345
-        case 0x63: conv= rgb15to24; break;
2346
-        case 0x64: conv= rgb16to24; break;
2347
-        case 0x68: conv= rgb32to24; break;
2348
-        case 0x83: conv= rgb15to32; break;
2349
-        case 0x84: conv= rgb16to32; break;
2350
-        case 0x86: conv= rgb24to32; break;
2351
-        }
2352
-    } else if (  (isBGRinInt(srcFormat) && isRGBinInt(dstFormat))
2353
-             || (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
2354
-        switch(srcId | (dstId<<4)) {
2355
-        case 0x33: conv= rgb15tobgr15; break;
2356
-        case 0x34: conv= rgb16tobgr15; break;
2357
-        case 0x36: conv= rgb24tobgr15; break;
2358
-        case 0x38: conv= rgb32tobgr15; break;
2359
-        case 0x43: conv= rgb15tobgr16; break;
2360
-        case 0x44: conv= rgb16tobgr16; break;
2361
-        case 0x46: conv= rgb24tobgr16; break;
2362
-        case 0x48: conv= rgb32tobgr16; break;
2363
-        case 0x63: conv= rgb15tobgr24; break;
2364
-        case 0x64: conv= rgb16tobgr24; break;
2365
-        case 0x66: conv= rgb24tobgr24; break;
2366
-        case 0x68: conv= rgb32tobgr24; break;
2367
-        case 0x83: conv= rgb15tobgr32; break;
2368
-        case 0x84: conv= rgb16tobgr32; break;
2369
-        case 0x86: conv= rgb24tobgr32; break;
2370
-        }
2371
-    }
2372
-
2373
-    if (!conv) {
2374
-        av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
2375
-               sws_format_name(srcFormat), sws_format_name(dstFormat));
2376
-    } else {
2377
-        const uint8_t *srcPtr= src[0];
2378
-              uint8_t *dstPtr= dst[0];
2379
-        if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && !isRGBA32(dstFormat))
2380
-            srcPtr += ALT32_CORR;
2381
-
2382
-        if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat))
2383
-            dstPtr += ALT32_CORR;
2384
-
2385
-        if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0)
2386
-            conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
2387
-        else {
2388
-            int i;
2389
-            dstPtr += dstStride[0]*srcSliceY;
2390
-
2391
-            for (i=0; i<srcSliceH; i++) {
2392
-                conv(srcPtr, dstPtr, c->srcW*srcBpp);
2393
-                srcPtr+= srcStride[0];
2394
-                dstPtr+= dstStride[0];
2395
-            }
2396
-        }
2397
-    }
2398
-    return srcSliceH;
2399
-}
2400
-
2401
-static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2402
-                              int srcSliceH, uint8_t* dst[], int dstStride[])
2403
-{
2404
-    rgb24toyv12(
2405
-        src[0],
2406
-        dst[0]+ srcSliceY    *dstStride[0],
2407
-        dst[1]+(srcSliceY>>1)*dstStride[1],
2408
-        dst[2]+(srcSliceY>>1)*dstStride[2],
2409
-        c->srcW, srcSliceH,
2410
-        dstStride[0], dstStride[1], srcStride[0]);
2411
-    if (dst[3])
2412
-        fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
2413
-    return srcSliceH;
2414
-}
2415
-
2416
-static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2417
-                             int srcSliceH, uint8_t* dst[], int dstStride[])
2418
-{
2419
-    copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
2420
-              dst[0], dstStride[0]);
2421
-
2422
-    planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW,
2423
-             srcSliceH >> 2, srcStride[1], dstStride[1]);
2424
-    planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW,
2425
-             srcSliceH >> 2, srcStride[2], dstStride[2]);
2426
-    if (dst[3])
2427
-        fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
2428
-    return srcSliceH;
2429
-}
2430
-
2431
-/* unscaled copy like stuff (assumes nearly identical formats) */
2432
-static int packedCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2433
-                             int srcSliceH, uint8_t* dst[], int dstStride[])
2434
-{
2435
-    if (dstStride[0]==srcStride[0] && srcStride[0] > 0)
2436
-        memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
2437
-    else {
2438
-        int i;
2439
-        const uint8_t *srcPtr= src[0];
2440
-        uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
2441
-        int length=0;
2442
-
2443
-        /* universal length finder */
2444
-        while(length+c->srcW <= FFABS(dstStride[0])
2445
-           && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW;
2446
-        assert(length!=0);
2447
-
2448
-        for (i=0; i<srcSliceH; i++) {
2449
-            memcpy(dstPtr, srcPtr, length);
2450
-            srcPtr+= srcStride[0];
2451
-            dstPtr+= dstStride[0];
2452
-        }
2453
-    }
2454
-    return srcSliceH;
2455
-}
2456
-
2457
-static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
2458
-                             int srcSliceH, uint8_t* dst[], int dstStride[])
2459
-{
2460
-    int plane, i, j;
2461
-    for (plane=0; plane<4; plane++) {
2462
-        int length= (plane==0 || plane==3) ? c->srcW  : -((-c->srcW  )>>c->chrDstHSubSample);
2463
-        int y=      (plane==0 || plane==3) ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
2464
-        int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
2465
-        const uint8_t *srcPtr= src[plane];
2466
-        uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
2467
-
2468
-        if (!dst[plane]) continue;
2469
-        // ignore palette for GRAY8
2470
-        if (plane == 1 && !dst[2]) continue;
2471
-        if (!src[plane] || (plane == 1 && !src[2])) {
2472
-            if(is16BPS(c->dstFormat))
2473
-                length*=2;
2474
-            fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128);
2475
-        } else {
2476
-            if(is9_OR_10BPS(c->srcFormat)) {
2477
-                const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1;
2478
-                const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
2479
-                const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
2480
-
2481
-                if (is16BPS(c->dstFormat)) {
2482
-                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
2483
-#define COPY9_OR_10TO16(rfunc, wfunc) \
2484
-                    for (i = 0; i < height; i++) { \
2485
-                        for (j = 0; j < length; j++) { \
2486
-                            int srcpx = rfunc(&srcPtr2[j]); \
2487
-                            wfunc(&dstPtr2[j], (srcpx<<(16-src_depth)) | (srcpx>>(2*src_depth-16))); \
2488
-                        } \
2489
-                        dstPtr2 += dstStride[plane]/2; \
2490
-                        srcPtr2 += srcStride[plane]/2; \
2491
-                    }
2492
-                    if (isBE(c->dstFormat)) {
2493
-                        if (isBE(c->srcFormat)) {
2494
-                            COPY9_OR_10TO16(AV_RB16, AV_WB16);
2495
-                        } else {
2496
-                            COPY9_OR_10TO16(AV_RL16, AV_WB16);
2497
-                        }
2498
-                    } else {
2499
-                        if (isBE(c->srcFormat)) {
2500
-                            COPY9_OR_10TO16(AV_RB16, AV_WL16);
2501
-                        } else {
2502
-                            COPY9_OR_10TO16(AV_RL16, AV_WL16);
2503
-                        }
2504
-                    }
2505
-                } else if (is9_OR_10BPS(c->dstFormat)) {
2506
-                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
2507
-#define COPY9_OR_10TO9_OR_10(loop) \
2508
-                    for (i = 0; i < height; i++) { \
2509
-                        for (j = 0; j < length; j++) { \
2510
-                            loop; \
2511
-                        } \
2512
-                        dstPtr2 += dstStride[plane]/2; \
2513
-                        srcPtr2 += srcStride[plane]/2; \
2514
-                    }
2515
-#define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \
2516
-                    if (dst_depth > src_depth) { \
2517
-                        COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \
2518
-                            wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \
2519
-                    } else if (dst_depth < src_depth) { \
2520
-                        COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]) >> 1)); \
2521
-                    } else { \
2522
-                        COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \
2523
-                    }
2524
-                    if (isBE(c->dstFormat)) {
2525
-                        if (isBE(c->srcFormat)) {
2526
-                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16);
2527
-                        } else {
2528
-                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16);
2529
-                        }
2530
-                    } else {
2531
-                        if (isBE(c->srcFormat)) {
2532
-                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16);
2533
-                        } else {
2534
-                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16);
2535
-                        }
2536
-                    }
2537
-                } else {
2538
-                    // FIXME Maybe dither instead.
2539
-#define COPY9_OR_10TO8(rfunc) \
2540
-                    for (i = 0; i < height; i++) { \
2541
-                        for (j = 0; j < length; j++) { \
2542
-                            dstPtr[j] = rfunc(&srcPtr2[j])>>(src_depth-8); \
2543
-                        } \
2544
-                        dstPtr  += dstStride[plane]; \
2545
-                        srcPtr2 += srcStride[plane]/2; \
2546
-                    }
2547
-                    if (isBE(c->srcFormat)) {
2548
-                        COPY9_OR_10TO8(AV_RB16);
2549
-                    } else {
2550
-                        COPY9_OR_10TO8(AV_RL16);
2551
-                    }
2552
-                }
2553
-            } else if(is9_OR_10BPS(c->dstFormat)) {
2554
-                const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
2555
-                uint16_t *dstPtr2 = (uint16_t*)dstPtr;
2556
-
2557
-                if (is16BPS(c->srcFormat)) {
2558
-                    const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
2559
-#define COPY16TO9_OR_10(rfunc, wfunc) \
2560
-                    for (i = 0; i < height; i++) { \
2561
-                        for (j = 0; j < length; j++) { \
2562
-                            wfunc(&dstPtr2[j], rfunc(&srcPtr2[j])>>(16-dst_depth)); \
2563
-                        } \
2564
-                        dstPtr2 += dstStride[plane]/2; \
2565
-                        srcPtr2 += srcStride[plane]/2; \
2566
-                    }
2567
-                    if (isBE(c->dstFormat)) {
2568
-                        if (isBE(c->srcFormat)) {
2569
-                            COPY16TO9_OR_10(AV_RB16, AV_WB16);
2570
-                        } else {
2571
-                            COPY16TO9_OR_10(AV_RL16, AV_WB16);
2572
-                        }
2573
-                    } else {
2574
-                        if (isBE(c->srcFormat)) {
2575
-                            COPY16TO9_OR_10(AV_RB16, AV_WL16);
2576
-                        } else {
2577
-                            COPY16TO9_OR_10(AV_RL16, AV_WL16);
2578
-                        }
2579
-                    }
2580
-                } else /* 8bit */ {
2581
-#define COPY8TO9_OR_10(wfunc) \
2582
-                    for (i = 0; i < height; i++) { \
2583
-                        for (j = 0; j < length; j++) { \
2584
-                            const int srcpx = srcPtr[j]; \
2585
-                            wfunc(&dstPtr2[j], (srcpx<<(dst_depth-8)) | (srcpx >> (16-dst_depth))); \
2586
-                        } \
2587
-                        dstPtr2 += dstStride[plane]/2; \
2588
-                        srcPtr  += srcStride[plane]; \
2589
-                    }
2590
-                    if (isBE(c->dstFormat)) {
2591
-                        COPY8TO9_OR_10(AV_WB16);
2592
-                    } else {
2593
-                        COPY8TO9_OR_10(AV_WL16);
2594
-                    }
2595
-                }
2596
-            } else if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {
2597
-                if (!isBE(c->srcFormat)) srcPtr++;
2598
-                for (i=0; i<height; i++) {
2599
-                    for (j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1];
2600
-                    srcPtr+= srcStride[plane];
2601
-                    dstPtr+= dstStride[plane];
2602
-                }
2603
-            } else if(!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) {
2604
-                for (i=0; i<height; i++) {
2605
-                    for (j=0; j<length; j++) {
2606
-                        dstPtr[ j<<1   ] = srcPtr[j];
2607
-                        dstPtr[(j<<1)+1] = srcPtr[j];
2608
-                    }
2609
-                    srcPtr+= srcStride[plane];
2610
-                    dstPtr+= dstStride[plane];
2611
-                }
2612
-            } else if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat)
2613
-                  && isBE(c->srcFormat) != isBE(c->dstFormat)) {
2614
-
2615
-                for (i=0; i<height; i++) {
2616
-                    for (j=0; j<length; j++)
2617
-                        ((uint16_t*)dstPtr)[j] = av_bswap16(((const uint16_t*)srcPtr)[j]);
2618
-                    srcPtr+= srcStride[plane];
2619
-                    dstPtr+= dstStride[plane];
2620
-                }
2621
-            } else if (dstStride[plane] == srcStride[plane] &&
2622
-                       srcStride[plane] > 0 && srcStride[plane] == length) {
2623
-                memcpy(dst[plane] + dstStride[plane]*y, src[plane],
2624
-                       height*dstStride[plane]);
2625
-            } else {
2626
-                if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
2627
-                    length*=2;
2628
-                for (i=0; i<height; i++) {
2629
-                    memcpy(dstPtr, srcPtr, length);
2630
-                    srcPtr+= srcStride[plane];
2631
-                    dstPtr+= dstStride[plane];
2632
-                }
2633
-            }
2634
-        }
2635
-    }
2636
-    return srcSliceH;
2637
-}
2638
-
2639
-void ff_get_unscaled_swscale(SwsContext *c)
2640
-{
2641
-    const enum PixelFormat srcFormat = c->srcFormat;
2642
-    const enum PixelFormat dstFormat = c->dstFormat;
2643
-    const int flags = c->flags;
2644
-    const int dstH = c->dstH;
2645
-    int needsDither;
2646
-
2647
-    needsDither= isAnyRGB(dstFormat)
2648
-        &&  c->dstFormatBpp < 24
2649
-        && (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
2650
-
2651
-    /* yv12_to_nv12 */
2652
-    if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) {
2653
-        c->swScale= planarToNv12Wrapper;
2654
-    }
2655
-    /* yuv2bgr */
2656
-    if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P || srcFormat==PIX_FMT_YUVA420P) && isAnyRGB(dstFormat)
2657
-        && !(flags & SWS_ACCURATE_RND) && !(dstH&1)) {
2658
-        c->swScale= ff_yuv2rgb_get_func_ptr(c);
2659
-    }
2660
-
2661
-    if (srcFormat==PIX_FMT_YUV410P && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_BITEXACT)) {
2662
-        c->swScale= yvu9ToYv12Wrapper;
2663
-    }
2664
-
2665
-    /* bgr24toYV12 */
2666
-    if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND))
2667
-        c->swScale= bgr24ToYv12Wrapper;
2668
-
2669
-    /* RGB/BGR -> RGB/BGR (no dither needed forms) */
2670
-    if (   isAnyRGB(srcFormat)
2671
-        && isAnyRGB(dstFormat)
2672
-        && srcFormat != PIX_FMT_BGR8      && dstFormat != PIX_FMT_BGR8
2673
-        && srcFormat != PIX_FMT_RGB8      && dstFormat != PIX_FMT_RGB8
2674
-        && srcFormat != PIX_FMT_BGR4      && dstFormat != PIX_FMT_BGR4
2675
-        && srcFormat != PIX_FMT_RGB4      && dstFormat != PIX_FMT_RGB4
2676
-        && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE
2677
-        && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE
2678
-        && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK
2679
-        && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE
2680
-        && srcFormat != PIX_FMT_RGB48LE   && dstFormat != PIX_FMT_RGB48LE
2681
-        && srcFormat != PIX_FMT_RGB48BE   && dstFormat != PIX_FMT_RGB48BE
2682
-        && srcFormat != PIX_FMT_BGR48LE   && dstFormat != PIX_FMT_BGR48LE
2683
-        && srcFormat != PIX_FMT_BGR48BE   && dstFormat != PIX_FMT_BGR48BE
2684
-        && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
2685
-        c->swScale= rgbToRgbWrapper;
2686
-
2687
-    if ((usePal(srcFormat) && (
2688
-        dstFormat == PIX_FMT_RGB32   ||
2689
-        dstFormat == PIX_FMT_RGB32_1 ||
2690
-        dstFormat == PIX_FMT_RGB24   ||
2691
-        dstFormat == PIX_FMT_BGR32   ||
2692
-        dstFormat == PIX_FMT_BGR32_1 ||
2693
-        dstFormat == PIX_FMT_BGR24)))
2694
-        c->swScale= palToRgbWrapper;
2695
-
2696
-    if (srcFormat == PIX_FMT_YUV422P) {
2697
-        if (dstFormat == PIX_FMT_YUYV422)
2698
-            c->swScale= yuv422pToYuy2Wrapper;
2699
-        else if (dstFormat == PIX_FMT_UYVY422)
2700
-            c->swScale= yuv422pToUyvyWrapper;
2701
-    }
2702
-
2703
-    /* LQ converters if -sws 0 or -sws 4*/
2704
-    if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
2705
-        /* yv12_to_yuy2 */
2706
-        if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) {
2707
-            if (dstFormat == PIX_FMT_YUYV422)
2708
-                c->swScale= planarToYuy2Wrapper;
2709
-            else if (dstFormat == PIX_FMT_UYVY422)
2710
-                c->swScale= planarToUyvyWrapper;
2711
-        }
2712
-    }
2713
-    if(srcFormat == PIX_FMT_YUYV422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
2714
-        c->swScale= yuyvToYuv420Wrapper;
2715
-    if(srcFormat == PIX_FMT_UYVY422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
2716
-        c->swScale= uyvyToYuv420Wrapper;
2717
-    if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
2718
-        c->swScale= yuyvToYuv422Wrapper;
2719
-    if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
2720
-        c->swScale= uyvyToYuv422Wrapper;
2721
-
2722
-    /* simple copy */
2723
-    if (  srcFormat == dstFormat
2724
-        || (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P)
2725
-        || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P)
2726
-        || (isPlanarYUV(srcFormat) && isGray(dstFormat))
2727
-        || (isPlanarYUV(dstFormat) && isGray(srcFormat))
2728
-        || (isGray(dstFormat) && isGray(srcFormat))
2729
-        || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat)
2730
-            && c->chrDstHSubSample == c->chrSrcHSubSample
2731
-            && c->chrDstVSubSample == c->chrSrcVSubSample
2732
-            && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21
2733
-            && srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21))
2734
-    {
2735
-        if (isPacked(c->srcFormat))
2736
-            c->swScale= packedCopyWrapper;
2737
-        else /* Planar YUV or gray */
2738
-            c->swScale= planarCopyWrapper;
2739
-    }
2740
-
2741
-    if (ARCH_BFIN)
2742
-        ff_bfin_get_unscaled_swscale(c);
2743
-    if (HAVE_ALTIVEC)
2744
-        ff_swscale_get_unscaled_altivec(c);
2745
-}
2746
-
2747
-static void reset_ptr(const uint8_t* src[], int format)
2748
-{
2749
-    if(!isALPHA(format))
2750
-        src[3]=NULL;
2751
-    if(!isPlanarYUV(format)) {
2752
-        src[3]=src[2]=NULL;
2753
-
2754
-        if (!usePal(format))
2755
-            src[1]= NULL;
2756
-    }
2757
-}
2758
-
2759
-static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt,
2760
-                                const int linesizes[4])
2761
-{
2762
-    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
2763
-    int i;
2764
-
2765
-    for (i = 0; i < 4; i++) {
2766
-        int plane = desc->comp[i].plane;
2767
-        if (!data[plane] || !linesizes[plane])
2768
-            return 0;
2769
-    }
2770
-
2771
-    return 1;
2772
-}
2773
-
2774
-/**
2775
- * swscale wrapper, so we don't need to export the SwsContext.
2776
- * Assumes planar YUV to be in YUV order instead of YVU.
2777
- */
2778
-int sws_scale(SwsContext *c, const uint8_t* const src[], const int srcStride[], int srcSliceY,
2779
-              int srcSliceH, uint8_t* const dst[], const int dstStride[])
2780
-{
2781
-    int i;
2782
-    const uint8_t* src2[4]= {src[0], src[1], src[2], src[3]};
2783
-    uint8_t* dst2[4]= {dst[0], dst[1], dst[2], dst[3]};
2784
-
2785
-    // do not mess up sliceDir if we have a "trailing" 0-size slice
2786
-    if (srcSliceH == 0)
2787
-        return 0;
2788
-
2789
-    if (!check_image_pointers(src, c->srcFormat, srcStride)) {
2790
-        av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
2791
-        return 0;
2792
-    }
2793
-    if (!check_image_pointers(dst, c->dstFormat, dstStride)) {
2794
-        av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
2795
-        return 0;
2796
-    }
2797
-
2798
-    if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
2799
-        av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
2800
-        return 0;
2801
-    }
2802
-    if (c->sliceDir == 0) {
2803
-        if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
2804
-    }
2805
-
2806
-    if (usePal(c->srcFormat)) {
2807
-        for (i=0; i<256; i++) {
2808
-            int p, r, g, b,y,u,v;
2809
-            if(c->srcFormat == PIX_FMT_PAL8) {
2810
-                p=((const uint32_t*)(src[1]))[i];
2811
-                r= (p>>16)&0xFF;
2812
-                g= (p>> 8)&0xFF;
2813
-                b=  p     &0xFF;
2814
-            } else if(c->srcFormat == PIX_FMT_RGB8) {
2815
-                r= (i>>5    )*36;
2816
-                g= ((i>>2)&7)*36;
2817
-                b= (i&3     )*85;
2818
-            } else if(c->srcFormat == PIX_FMT_BGR8) {
2819
-                b= (i>>6    )*85;
2820
-                g= ((i>>3)&7)*36;
2821
-                r= (i&7     )*36;
2822
-            } else if(c->srcFormat == PIX_FMT_RGB4_BYTE) {
2823
-                r= (i>>3    )*255;
2824
-                g= ((i>>1)&3)*85;
2825
-                b= (i&1     )*255;
2826
-            } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_Y400A) {
2827
-                r = g = b = i;
2828
-            } else {
2829
-                assert(c->srcFormat == PIX_FMT_BGR4_BYTE);
2830
-                b= (i>>3    )*255;
2831
-                g= ((i>>1)&3)*85;
2832
-                r= (i&1     )*255;
2833
-            }
2834
-            y= av_clip_uint8((RY*r + GY*g + BY*b + ( 33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
2835
-            u= av_clip_uint8((RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
2836
-            v= av_clip_uint8((RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
2837
-            c->pal_yuv[i]= y + (u<<8) + (v<<16);
2838
-
2839
-            switch(c->dstFormat) {
2840
-            case PIX_FMT_BGR32:
2841
-#if !HAVE_BIGENDIAN
2842
-            case PIX_FMT_RGB24:
2843
-#endif
2844
-                c->pal_rgb[i]=  r + (g<<8) + (b<<16);
2845
-                break;
2846
-            case PIX_FMT_BGR32_1:
2847
-#if HAVE_BIGENDIAN
2848
-            case PIX_FMT_BGR24:
2849
-#endif
2850
-                c->pal_rgb[i]= (r + (g<<8) + (b<<16)) << 8;
2851
-                break;
2852
-            case PIX_FMT_RGB32_1:
2853
-#if HAVE_BIGENDIAN
2854
-            case PIX_FMT_RGB24:
2855
-#endif
2856
-                c->pal_rgb[i]= (b + (g<<8) + (r<<16)) << 8;
2857
-                break;
2858
-            case PIX_FMT_RGB32:
2859
-#if !HAVE_BIGENDIAN
2860
-            case PIX_FMT_BGR24:
2861
-#endif
2862
-            default:
2863
-                c->pal_rgb[i]=  b + (g<<8) + (r<<16);
2864
-            }
2865
-        }
2866
-    }
2867
-
2868
-    // copy strides, so they can safely be modified
2869
-    if (c->sliceDir == 1) {
2870
-        // slices go from top to bottom
2871
-        int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2], srcStride[3]};
2872
-        int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]};
2873
-
2874
-        reset_ptr(src2, c->srcFormat);
2875
-        reset_ptr((const uint8_t**)dst2, c->dstFormat);
2876
-
2877
-        /* reset slice direction at end of frame */
2878
-        if (srcSliceY + srcSliceH == c->srcH)
2879
-            c->sliceDir = 0;
2880
-
2881
-        return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, dstStride2);
2882
-    } else {
2883
-        // slices go from bottom to top => we flip the image internally
2884
-        int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2], -srcStride[3]};
2885
-        int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2], -dstStride[3]};
2886
-
2887
-        src2[0] += (srcSliceH-1)*srcStride[0];
2888
-        if (!usePal(c->srcFormat))
2889
-            src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1];
2890
-        src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2];
2891
-        src2[3] += (srcSliceH-1)*srcStride[3];
2892
-        dst2[0] += ( c->dstH                      -1)*dstStride[0];
2893
-        dst2[1] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1];
2894
-        dst2[2] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2];
2895
-        dst2[3] += ( c->dstH                      -1)*dstStride[3];
2896
-
2897
-        reset_ptr(src2, c->srcFormat);
2898
-        reset_ptr((const uint8_t**)dst2, c->dstFormat);
2899
-
2900
-        /* reset slice direction at end of frame */
2901
-        if (!srcSliceY)
2902
-            c->sliceDir = 0;
2903
-
2904
-        return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2);
2905
-    }
2906
-}
2907
-
2908
-/* Convert the palette to the same packed 32-bit format as the palette */
2909
-void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
2910
-{
2911
-    int i;
2912
-
2913
-    for (i=0; i<num_pixels; i++)
2914
-        ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
2915
-}
2916
-
2917
-/* Palette format: ABCD -> dst format: ABC */
2918
-void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
2919
-{
2920
-    int i;
2921
-
2922
-    for (i=0; i<num_pixels; i++) {
2923
-        //FIXME slow?
2924
-        dst[0]= palette[src[i]*4+0];
2925
-        dst[1]= palette[src[i]*4+1];
2926
-        dst[2]= palette[src[i]*4+2];
2927
-        dst+= 3;
2928
-    }
2929
-}
... ...
@@ -464,6 +464,13 @@ const char *sws_format_name(enum PixelFormat format);
464 464
         || (x)==PIX_FMT_Y400A       \
465 465
         || (x)==PIX_FMT_YUVA420P    \
466 466
     )
467
+#define isPacked(x)         (       \
468
+           (x)==PIX_FMT_PAL8        \
469
+        || (x)==PIX_FMT_YUYV422     \
470
+        || (x)==PIX_FMT_UYVY422     \
471
+        || (x)==PIX_FMT_Y400A       \
472
+        || isAnyRGB(x)              \
473
+    )
467 474
 #define usePal(x) ((av_pix_fmt_descriptors[x].flags & PIX_FMT_PAL) || (x) == PIX_FMT_Y400A)
468 475
 
469 476
 extern const uint64_t ff_dither4[2];
470 477
new file mode 100644
... ...
@@ -0,0 +1,887 @@
0
+/*
1
+ * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
2
+ *
3
+ * This file is part of Libav.
4
+ *
5
+ * Libav is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * Libav is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with Libav; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include <inttypes.h>
21
+#include <string.h>
22
+#include <math.h>
23
+#include <stdio.h>
24
+#include "config.h"
25
+#include <assert.h>
26
+#include "swscale.h"
27
+#include "swscale_internal.h"
28
+#include "rgb2rgb.h"
29
+#include "libavutil/intreadwrite.h"
30
+#include "libavutil/cpu.h"
31
+#include "libavutil/avutil.h"
32
+#include "libavutil/mathematics.h"
33
+#include "libavutil/bswap.h"
34
+#include "libavutil/pixdesc.h"
35
+
36
+#define RGB2YUV_SHIFT 15
37
+#define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
38
+#define BV (-(int)(0.081*224/255*(1<<RGB2YUV_SHIFT)+0.5))
39
+#define BU ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
40
+#define GY ( (int)(0.587*219/255*(1<<RGB2YUV_SHIFT)+0.5))
41
+#define GV (-(int)(0.419*224/255*(1<<RGB2YUV_SHIFT)+0.5))
42
+#define GU (-(int)(0.331*224/255*(1<<RGB2YUV_SHIFT)+0.5))
43
+#define RY ( (int)(0.299*219/255*(1<<RGB2YUV_SHIFT)+0.5))
44
+#define RV ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
45
+#define RU (-(int)(0.169*224/255*(1<<RGB2YUV_SHIFT)+0.5))
46
+
47
+static void fillPlane(uint8_t* plane, int stride, int width, int height, int y, uint8_t val)
48
+{
49
+    int i;
50
+    uint8_t *ptr = plane + stride*y;
51
+    for (i=0; i<height; i++) {
52
+        memset(ptr, val, width);
53
+        ptr += stride;
54
+    }
55
+}
56
+
57
+static void copyPlane(const uint8_t *src, int srcStride,
58
+                      int srcSliceY, int srcSliceH, int width,
59
+                      uint8_t *dst, int dstStride)
60
+{
61
+    dst += dstStride * srcSliceY;
62
+    if (dstStride == srcStride && srcStride > 0) {
63
+        memcpy(dst, src, srcSliceH * dstStride);
64
+    } else {
65
+        int i;
66
+        for (i=0; i<srcSliceH; i++) {
67
+            memcpy(dst, src, width);
68
+            src += srcStride;
69
+            dst += dstStride;
70
+        }
71
+    }
72
+}
73
+
74
+static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
75
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
76
+{
77
+    uint8_t *dst = dstParam[1] + dstStride[1]*srcSliceY/2;
78
+
79
+    copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
80
+              dstParam[0], dstStride[0]);
81
+
82
+    if (c->dstFormat == PIX_FMT_NV12)
83
+        interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]);
84
+    else
85
+        interleaveBytes(src[2], src[1], dst, c->srcW/2, srcSliceH/2, srcStride[2], srcStride[1], dstStride[0]);
86
+
87
+    return srcSliceH;
88
+}
89
+
90
+static int planarToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
91
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
92
+{
93
+    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
94
+
95
+    yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
96
+
97
+    return srcSliceH;
98
+}
99
+
100
+static int planarToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
101
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
102
+{
103
+    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
104
+
105
+    yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
106
+
107
+    return srcSliceH;
108
+}
109
+
110
+static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
111
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
112
+{
113
+    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
114
+
115
+    yuv422ptoyuy2(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
116
+
117
+    return srcSliceH;
118
+}
119
+
120
+static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
121
+                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
122
+{
123
+    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
124
+
125
+    yuv422ptouyvy(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
126
+
127
+    return srcSliceH;
128
+}
129
+
130
+static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
131
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
132
+{
133
+    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
134
+    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
135
+    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
136
+
137
+    yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
138
+
139
+    if (dstParam[3])
140
+        fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
141
+
142
+    return srcSliceH;
143
+}
144
+
145
+static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
146
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
147
+{
148
+    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
149
+    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
150
+    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
151
+
152
+    yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
153
+
154
+    return srcSliceH;
155
+}
156
+
157
+static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
158
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
159
+{
160
+    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
161
+    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
162
+    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
163
+
164
+    uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
165
+
166
+    if (dstParam[3])
167
+        fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
168
+
169
+    return srcSliceH;
170
+}
171
+
172
+static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
173
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[])
174
+{
175
+    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
176
+    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
177
+    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
178
+
179
+    uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
180
+
181
+    return srcSliceH;
182
+}
183
+
184
+static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
185
+{
186
+    int i;
187
+    for (i=0; i<num_pixels; i++)
188
+        ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | (src[(i<<1)+1] << 24);
189
+}
190
+
191
+static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
192
+{
193
+    int i;
194
+
195
+    for (i=0; i<num_pixels; i++)
196
+        ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | src[(i<<1)+1];
197
+}
198
+
199
+static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
200
+{
201
+    int i;
202
+
203
+    for (i=0; i<num_pixels; i++) {
204
+        //FIXME slow?
205
+        dst[0]= palette[src[i<<1]*4+0];
206
+        dst[1]= palette[src[i<<1]*4+1];
207
+        dst[2]= palette[src[i<<1]*4+2];
208
+        dst+= 3;
209
+    }
210
+}
211
+
212
+static int palToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
213
+                           int srcSliceH, uint8_t* dst[], int dstStride[])
214
+{
215
+    const enum PixelFormat srcFormat= c->srcFormat;
216
+    const enum PixelFormat dstFormat= c->dstFormat;
217
+    void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
218
+                 const uint8_t *palette)=NULL;
219
+    int i;
220
+    uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
221
+    const uint8_t *srcPtr= src[0];
222
+
223
+    if (srcFormat == PIX_FMT_Y400A) {
224
+        switch (dstFormat) {
225
+        case PIX_FMT_RGB32  : conv = gray8aToPacked32; break;
226
+        case PIX_FMT_BGR32  : conv = gray8aToPacked32; break;
227
+        case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
228
+        case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
229
+        case PIX_FMT_RGB24  : conv = gray8aToPacked24; break;
230
+        case PIX_FMT_BGR24  : conv = gray8aToPacked24; break;
231
+        }
232
+    } else if (usePal(srcFormat)) {
233
+        switch (dstFormat) {
234
+        case PIX_FMT_RGB32  : conv = sws_convertPalette8ToPacked32; break;
235
+        case PIX_FMT_BGR32  : conv = sws_convertPalette8ToPacked32; break;
236
+        case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
237
+        case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
238
+        case PIX_FMT_RGB24  : conv = sws_convertPalette8ToPacked24; break;
239
+        case PIX_FMT_BGR24  : conv = sws_convertPalette8ToPacked24; break;
240
+        }
241
+    }
242
+
243
+    if (!conv)
244
+        av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
245
+               sws_format_name(srcFormat), sws_format_name(dstFormat));
246
+    else {
247
+        for (i=0; i<srcSliceH; i++) {
248
+            conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
249
+            srcPtr+= srcStride[0];
250
+            dstPtr+= dstStride[0];
251
+        }
252
+    }
253
+
254
+    return srcSliceH;
255
+}
256
+
257
+#define isRGBA32(x) (            \
258
+           (x) == PIX_FMT_ARGB   \
259
+        || (x) == PIX_FMT_RGBA   \
260
+        || (x) == PIX_FMT_BGRA   \
261
+        || (x) == PIX_FMT_ABGR   \
262
+        )
263
+
264
+/* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
265
+static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
266
+                           int srcSliceH, uint8_t* dst[], int dstStride[])
267
+{
268
+    const enum PixelFormat srcFormat= c->srcFormat;
269
+    const enum PixelFormat dstFormat= c->dstFormat;
270
+    const int srcBpp= (c->srcFormatBpp + 7) >> 3;
271
+    const int dstBpp= (c->dstFormatBpp + 7) >> 3;
272
+    const int srcId= c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */
273
+    const int dstId= c->dstFormatBpp >> 2;
274
+    void (*conv)(const uint8_t *src, uint8_t *dst, int src_size)=NULL;
275
+
276
+#define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst)
277
+
278
+    if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
279
+        if (     CONV_IS(ABGR, RGBA)
280
+              || CONV_IS(ARGB, BGRA)
281
+              || CONV_IS(BGRA, ARGB)
282
+              || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
283
+        else if (CONV_IS(ABGR, ARGB)
284
+              || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
285
+        else if (CONV_IS(ABGR, BGRA)
286
+              || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
287
+        else if (CONV_IS(BGRA, RGBA)
288
+              || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
289
+        else if (CONV_IS(BGRA, ABGR)
290
+              || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
291
+    } else
292
+    /* BGR -> BGR */
293
+    if (  (isBGRinInt(srcFormat) && isBGRinInt(dstFormat))
294
+       || (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
295
+        switch(srcId | (dstId<<4)) {
296
+        case 0x34: conv= rgb16to15; break;
297
+        case 0x36: conv= rgb24to15; break;
298
+        case 0x38: conv= rgb32to15; break;
299
+        case 0x43: conv= rgb15to16; break;
300
+        case 0x46: conv= rgb24to16; break;
301
+        case 0x48: conv= rgb32to16; break;
302
+        case 0x63: conv= rgb15to24; break;
303
+        case 0x64: conv= rgb16to24; break;
304
+        case 0x68: conv= rgb32to24; break;
305
+        case 0x83: conv= rgb15to32; break;
306
+        case 0x84: conv= rgb16to32; break;
307
+        case 0x86: conv= rgb24to32; break;
308
+        }
309
+    } else if (  (isBGRinInt(srcFormat) && isRGBinInt(dstFormat))
310
+             || (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
311
+        switch(srcId | (dstId<<4)) {
312
+        case 0x33: conv= rgb15tobgr15; break;
313
+        case 0x34: conv= rgb16tobgr15; break;
314
+        case 0x36: conv= rgb24tobgr15; break;
315
+        case 0x38: conv= rgb32tobgr15; break;
316
+        case 0x43: conv= rgb15tobgr16; break;
317
+        case 0x44: conv= rgb16tobgr16; break;
318
+        case 0x46: conv= rgb24tobgr16; break;
319
+        case 0x48: conv= rgb32tobgr16; break;
320
+        case 0x63: conv= rgb15tobgr24; break;
321
+        case 0x64: conv= rgb16tobgr24; break;
322
+        case 0x66: conv= rgb24tobgr24; break;
323
+        case 0x68: conv= rgb32tobgr24; break;
324
+        case 0x83: conv= rgb15tobgr32; break;
325
+        case 0x84: conv= rgb16tobgr32; break;
326
+        case 0x86: conv= rgb24tobgr32; break;
327
+        }
328
+    }
329
+
330
+    if (!conv) {
331
+        av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
332
+               sws_format_name(srcFormat), sws_format_name(dstFormat));
333
+    } else {
334
+        const uint8_t *srcPtr= src[0];
335
+              uint8_t *dstPtr= dst[0];
336
+        if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && !isRGBA32(dstFormat))
337
+            srcPtr += ALT32_CORR;
338
+
339
+        if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat))
340
+            dstPtr += ALT32_CORR;
341
+
342
+        if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0)
343
+            conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
344
+        else {
345
+            int i;
346
+            dstPtr += dstStride[0]*srcSliceY;
347
+
348
+            for (i=0; i<srcSliceH; i++) {
349
+                conv(srcPtr, dstPtr, c->srcW*srcBpp);
350
+                srcPtr+= srcStride[0];
351
+                dstPtr+= dstStride[0];
352
+            }
353
+        }
354
+    }
355
+    return srcSliceH;
356
+}
357
+
358
+static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
359
+                              int srcSliceH, uint8_t* dst[], int dstStride[])
360
+{
361
+    rgb24toyv12(
362
+        src[0],
363
+        dst[0]+ srcSliceY    *dstStride[0],
364
+        dst[1]+(srcSliceY>>1)*dstStride[1],
365
+        dst[2]+(srcSliceY>>1)*dstStride[2],
366
+        c->srcW, srcSliceH,
367
+        dstStride[0], dstStride[1], srcStride[0]);
368
+    if (dst[3])
369
+        fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
370
+    return srcSliceH;
371
+}
372
+
373
+static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
374
+                             int srcSliceH, uint8_t* dst[], int dstStride[])
375
+{
376
+    copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
377
+              dst[0], dstStride[0]);
378
+
379
+    planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW,
380
+             srcSliceH >> 2, srcStride[1], dstStride[1]);
381
+    planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW,
382
+             srcSliceH >> 2, srcStride[2], dstStride[2]);
383
+    if (dst[3])
384
+        fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
385
+    return srcSliceH;
386
+}
387
+
388
+/* unscaled copy like stuff (assumes nearly identical formats) */
389
+static int packedCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
390
+                             int srcSliceH, uint8_t* dst[], int dstStride[])
391
+{
392
+    if (dstStride[0]==srcStride[0] && srcStride[0] > 0)
393
+        memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
394
+    else {
395
+        int i;
396
+        const uint8_t *srcPtr= src[0];
397
+        uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
398
+        int length=0;
399
+
400
+        /* universal length finder */
401
+        while(length+c->srcW <= FFABS(dstStride[0])
402
+           && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW;
403
+        assert(length!=0);
404
+
405
+        for (i=0; i<srcSliceH; i++) {
406
+            memcpy(dstPtr, srcPtr, length);
407
+            srcPtr+= srcStride[0];
408
+            dstPtr+= dstStride[0];
409
+        }
410
+    }
411
+    return srcSliceH;
412
+}
413
+
414
+static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
415
+                             int srcSliceH, uint8_t* dst[], int dstStride[])
416
+{
417
+    int plane, i, j;
418
+    for (plane=0; plane<4; plane++) {
419
+        int length= (plane==0 || plane==3) ? c->srcW  : -((-c->srcW  )>>c->chrDstHSubSample);
420
+        int y=      (plane==0 || plane==3) ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
421
+        int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
422
+        const uint8_t *srcPtr= src[plane];
423
+        uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
424
+
425
+        if (!dst[plane]) continue;
426
+        // ignore palette for GRAY8
427
+        if (plane == 1 && !dst[2]) continue;
428
+        if (!src[plane] || (plane == 1 && !src[2])) {
429
+            if(is16BPS(c->dstFormat))
430
+                length*=2;
431
+            fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128);
432
+        } else {
433
+            if(is9_OR_10BPS(c->srcFormat)) {
434
+                const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1;
435
+                const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
436
+                const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
437
+
438
+                if (is16BPS(c->dstFormat)) {
439
+                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
440
+#define COPY9_OR_10TO16(rfunc, wfunc) \
441
+                    for (i = 0; i < height; i++) { \
442
+                        for (j = 0; j < length; j++) { \
443
+                            int srcpx = rfunc(&srcPtr2[j]); \
444
+                            wfunc(&dstPtr2[j], (srcpx<<(16-src_depth)) | (srcpx>>(2*src_depth-16))); \
445
+                        } \
446
+                        dstPtr2 += dstStride[plane]/2; \
447
+                        srcPtr2 += srcStride[plane]/2; \
448
+                    }
449
+                    if (isBE(c->dstFormat)) {
450
+                        if (isBE(c->srcFormat)) {
451
+                            COPY9_OR_10TO16(AV_RB16, AV_WB16);
452
+                        } else {
453
+                            COPY9_OR_10TO16(AV_RL16, AV_WB16);
454
+                        }
455
+                    } else {
456
+                        if (isBE(c->srcFormat)) {
457
+                            COPY9_OR_10TO16(AV_RB16, AV_WL16);
458
+                        } else {
459
+                            COPY9_OR_10TO16(AV_RL16, AV_WL16);
460
+                        }
461
+                    }
462
+                } else if (is9_OR_10BPS(c->dstFormat)) {
463
+                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
464
+#define COPY9_OR_10TO9_OR_10(loop) \
465
+                    for (i = 0; i < height; i++) { \
466
+                        for (j = 0; j < length; j++) { \
467
+                            loop; \
468
+                        } \
469
+                        dstPtr2 += dstStride[plane]/2; \
470
+                        srcPtr2 += srcStride[plane]/2; \
471
+                    }
472
+#define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \
473
+                    if (dst_depth > src_depth) { \
474
+                        COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \
475
+                            wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \
476
+                    } else if (dst_depth < src_depth) { \
477
+                        COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]) >> 1)); \
478
+                    } else { \
479
+                        COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \
480
+                    }
481
+                    if (isBE(c->dstFormat)) {
482
+                        if (isBE(c->srcFormat)) {
483
+                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16);
484
+                        } else {
485
+                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16);
486
+                        }
487
+                    } else {
488
+                        if (isBE(c->srcFormat)) {
489
+                            COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16);
490
+                        } else {
491
+                            COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16);
492
+                        }
493
+                    }
494
+                } else {
495
+                    // FIXME Maybe dither instead.
496
+#define COPY9_OR_10TO8(rfunc) \
497
+                    for (i = 0; i < height; i++) { \
498
+                        for (j = 0; j < length; j++) { \
499
+                            dstPtr[j] = rfunc(&srcPtr2[j])>>(src_depth-8); \
500
+                        } \
501
+                        dstPtr  += dstStride[plane]; \
502
+                        srcPtr2 += srcStride[plane]/2; \
503
+                    }
504
+                    if (isBE(c->srcFormat)) {
505
+                        COPY9_OR_10TO8(AV_RB16);
506
+                    } else {
507
+                        COPY9_OR_10TO8(AV_RL16);
508
+                    }
509
+                }
510
+            } else if(is9_OR_10BPS(c->dstFormat)) {
511
+                const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
512
+                uint16_t *dstPtr2 = (uint16_t*)dstPtr;
513
+
514
+                if (is16BPS(c->srcFormat)) {
515
+                    const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
516
+#define COPY16TO9_OR_10(rfunc, wfunc) \
517
+                    for (i = 0; i < height; i++) { \
518
+                        for (j = 0; j < length; j++) { \
519
+                            wfunc(&dstPtr2[j], rfunc(&srcPtr2[j])>>(16-dst_depth)); \
520
+                        } \
521
+                        dstPtr2 += dstStride[plane]/2; \
522
+                        srcPtr2 += srcStride[plane]/2; \
523
+                    }
524
+                    if (isBE(c->dstFormat)) {
525
+                        if (isBE(c->srcFormat)) {
526
+                            COPY16TO9_OR_10(AV_RB16, AV_WB16);
527
+                        } else {
528
+                            COPY16TO9_OR_10(AV_RL16, AV_WB16);
529
+                        }
530
+                    } else {
531
+                        if (isBE(c->srcFormat)) {
532
+                            COPY16TO9_OR_10(AV_RB16, AV_WL16);
533
+                        } else {
534
+                            COPY16TO9_OR_10(AV_RL16, AV_WL16);
535
+                        }
536
+                    }
537
+                } else /* 8bit */ {
538
+#define COPY8TO9_OR_10(wfunc) \
539
+                    for (i = 0; i < height; i++) { \
540
+                        for (j = 0; j < length; j++) { \
541
+                            const int srcpx = srcPtr[j]; \
542
+                            wfunc(&dstPtr2[j], (srcpx<<(dst_depth-8)) | (srcpx >> (16-dst_depth))); \
543
+                        } \
544
+                        dstPtr2 += dstStride[plane]/2; \
545
+                        srcPtr  += srcStride[plane]; \
546
+                    }
547
+                    if (isBE(c->dstFormat)) {
548
+                        COPY8TO9_OR_10(AV_WB16);
549
+                    } else {
550
+                        COPY8TO9_OR_10(AV_WL16);
551
+                    }
552
+                }
553
+            } else if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {
554
+                if (!isBE(c->srcFormat)) srcPtr++;
555
+                for (i=0; i<height; i++) {
556
+                    for (j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1];
557
+                    srcPtr+= srcStride[plane];
558
+                    dstPtr+= dstStride[plane];
559
+                }
560
+            } else if(!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) {
561
+                for (i=0; i<height; i++) {
562
+                    for (j=0; j<length; j++) {
563
+                        dstPtr[ j<<1   ] = srcPtr[j];
564
+                        dstPtr[(j<<1)+1] = srcPtr[j];
565
+                    }
566
+                    srcPtr+= srcStride[plane];
567
+                    dstPtr+= dstStride[plane];
568
+                }
569
+            } else if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat)
570
+                  && isBE(c->srcFormat) != isBE(c->dstFormat)) {
571
+
572
+                for (i=0; i<height; i++) {
573
+                    for (j=0; j<length; j++)
574
+                        ((uint16_t*)dstPtr)[j] = av_bswap16(((const uint16_t*)srcPtr)[j]);
575
+                    srcPtr+= srcStride[plane];
576
+                    dstPtr+= dstStride[plane];
577
+                }
578
+            } else if (dstStride[plane] == srcStride[plane] &&
579
+                       srcStride[plane] > 0 && srcStride[plane] == length) {
580
+                memcpy(dst[plane] + dstStride[plane]*y, src[plane],
581
+                       height*dstStride[plane]);
582
+            } else {
583
+                if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
584
+                    length*=2;
585
+                for (i=0; i<height; i++) {
586
+                    memcpy(dstPtr, srcPtr, length);
587
+                    srcPtr+= srcStride[plane];
588
+                    dstPtr+= dstStride[plane];
589
+                }
590
+            }
591
+        }
592
+    }
593
+    return srcSliceH;
594
+}
595
+
596
+void ff_get_unscaled_swscale(SwsContext *c)
597
+{
598
+    const enum PixelFormat srcFormat = c->srcFormat;
599
+    const enum PixelFormat dstFormat = c->dstFormat;
600
+    const int flags = c->flags;
601
+    const int dstH = c->dstH;
602
+    int needsDither;
603
+
604
+    needsDither= isAnyRGB(dstFormat)
605
+        &&  c->dstFormatBpp < 24
606
+        && (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
607
+
608
+    /* yv12_to_nv12 */
609
+    if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) {
610
+        c->swScale= planarToNv12Wrapper;
611
+    }
612
+    /* yuv2bgr */
613
+    if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P || srcFormat==PIX_FMT_YUVA420P) && isAnyRGB(dstFormat)
614
+        && !(flags & SWS_ACCURATE_RND) && !(dstH&1)) {
615
+        c->swScale= ff_yuv2rgb_get_func_ptr(c);
616
+    }
617
+
618
+    if (srcFormat==PIX_FMT_YUV410P && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_BITEXACT)) {
619
+        c->swScale= yvu9ToYv12Wrapper;
620
+    }
621
+
622
+    /* bgr24toYV12 */
623
+    if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND))
624
+        c->swScale= bgr24ToYv12Wrapper;
625
+
626
+    /* RGB/BGR -> RGB/BGR (no dither needed forms) */
627
+    if (   isAnyRGB(srcFormat)
628
+        && isAnyRGB(dstFormat)
629
+        && srcFormat != PIX_FMT_BGR8      && dstFormat != PIX_FMT_BGR8
630
+        && srcFormat != PIX_FMT_RGB8      && dstFormat != PIX_FMT_RGB8
631
+        && srcFormat != PIX_FMT_BGR4      && dstFormat != PIX_FMT_BGR4
632
+        && srcFormat != PIX_FMT_RGB4      && dstFormat != PIX_FMT_RGB4
633
+        && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE
634
+        && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE
635
+        && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK
636
+        && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE
637
+        && srcFormat != PIX_FMT_RGB48LE   && dstFormat != PIX_FMT_RGB48LE
638
+        && srcFormat != PIX_FMT_RGB48BE   && dstFormat != PIX_FMT_RGB48BE
639
+        && srcFormat != PIX_FMT_BGR48LE   && dstFormat != PIX_FMT_BGR48LE
640
+        && srcFormat != PIX_FMT_BGR48BE   && dstFormat != PIX_FMT_BGR48BE
641
+        && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
642
+        c->swScale= rgbToRgbWrapper;
643
+
644
+    if ((usePal(srcFormat) && (
645
+        dstFormat == PIX_FMT_RGB32   ||
646
+        dstFormat == PIX_FMT_RGB32_1 ||
647
+        dstFormat == PIX_FMT_RGB24   ||
648
+        dstFormat == PIX_FMT_BGR32   ||
649
+        dstFormat == PIX_FMT_BGR32_1 ||
650
+        dstFormat == PIX_FMT_BGR24)))
651
+        c->swScale= palToRgbWrapper;
652
+
653
+    if (srcFormat == PIX_FMT_YUV422P) {
654
+        if (dstFormat == PIX_FMT_YUYV422)
655
+            c->swScale= yuv422pToYuy2Wrapper;
656
+        else if (dstFormat == PIX_FMT_UYVY422)
657
+            c->swScale= yuv422pToUyvyWrapper;
658
+    }
659
+
660
+    /* LQ converters if -sws 0 or -sws 4*/
661
+    if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
662
+        /* yv12_to_yuy2 */
663
+        if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) {
664
+            if (dstFormat == PIX_FMT_YUYV422)
665
+                c->swScale= planarToYuy2Wrapper;
666
+            else if (dstFormat == PIX_FMT_UYVY422)
667
+                c->swScale= planarToUyvyWrapper;
668
+        }
669
+    }
670
+    if(srcFormat == PIX_FMT_YUYV422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
671
+        c->swScale= yuyvToYuv420Wrapper;
672
+    if(srcFormat == PIX_FMT_UYVY422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
673
+        c->swScale= uyvyToYuv420Wrapper;
674
+    if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
675
+        c->swScale= yuyvToYuv422Wrapper;
676
+    if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
677
+        c->swScale= uyvyToYuv422Wrapper;
678
+
679
+    /* simple copy */
680
+    if (  srcFormat == dstFormat
681
+        || (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P)
682
+        || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P)
683
+        || (isPlanarYUV(srcFormat) && isGray(dstFormat))
684
+        || (isPlanarYUV(dstFormat) && isGray(srcFormat))
685
+        || (isGray(dstFormat) && isGray(srcFormat))
686
+        || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat)
687
+            && c->chrDstHSubSample == c->chrSrcHSubSample
688
+            && c->chrDstVSubSample == c->chrSrcVSubSample
689
+            && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21
690
+            && srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21))
691
+    {
692
+        if (isPacked(c->srcFormat))
693
+            c->swScale= packedCopyWrapper;
694
+        else /* Planar YUV or gray */
695
+            c->swScale= planarCopyWrapper;
696
+    }
697
+
698
+    if (ARCH_BFIN)
699
+        ff_bfin_get_unscaled_swscale(c);
700
+    if (HAVE_ALTIVEC)
701
+        ff_swscale_get_unscaled_altivec(c);
702
+}
703
+
704
+static void reset_ptr(const uint8_t* src[], int format)
705
+{
706
+    if(!isALPHA(format))
707
+        src[3]=NULL;
708
+    if(!isPlanarYUV(format)) {
709
+        src[3]=src[2]=NULL;
710
+
711
+        if (!usePal(format))
712
+            src[1]= NULL;
713
+    }
714
+}
715
+
716
+static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt,
717
+                                const int linesizes[4])
718
+{
719
+    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
720
+    int i;
721
+
722
+    for (i = 0; i < 4; i++) {
723
+        int plane = desc->comp[i].plane;
724
+        if (!data[plane] || !linesizes[plane])
725
+            return 0;
726
+    }
727
+
728
+    return 1;
729
+}
730
+
731
+/**
732
+ * swscale wrapper, so we don't need to export the SwsContext.
733
+ * Assumes planar YUV to be in YUV order instead of YVU.
734
+ */
735
+int sws_scale(SwsContext *c, const uint8_t* const src[], const int srcStride[], int srcSliceY,
736
+              int srcSliceH, uint8_t* const dst[], const int dstStride[])
737
+{
738
+    int i;
739
+    const uint8_t* src2[4]= {src[0], src[1], src[2], src[3]};
740
+    uint8_t* dst2[4]= {dst[0], dst[1], dst[2], dst[3]};
741
+
742
+    // do not mess up sliceDir if we have a "trailing" 0-size slice
743
+    if (srcSliceH == 0)
744
+        return 0;
745
+
746
+    if (!check_image_pointers(src, c->srcFormat, srcStride)) {
747
+        av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
748
+        return 0;
749
+    }
750
+    if (!check_image_pointers(dst, c->dstFormat, dstStride)) {
751
+        av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
752
+        return 0;
753
+    }
754
+
755
+    if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
756
+        av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
757
+        return 0;
758
+    }
759
+    if (c->sliceDir == 0) {
760
+        if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
761
+    }
762
+
763
+    if (usePal(c->srcFormat)) {
764
+        for (i=0; i<256; i++) {
765
+            int p, r, g, b,y,u,v;
766
+            if(c->srcFormat == PIX_FMT_PAL8) {
767
+                p=((const uint32_t*)(src[1]))[i];
768
+                r= (p>>16)&0xFF;
769
+                g= (p>> 8)&0xFF;
770
+                b=  p     &0xFF;
771
+            } else if(c->srcFormat == PIX_FMT_RGB8) {
772
+                r= (i>>5    )*36;
773
+                g= ((i>>2)&7)*36;
774
+                b= (i&3     )*85;
775
+            } else if(c->srcFormat == PIX_FMT_BGR8) {
776
+                b= (i>>6    )*85;
777
+                g= ((i>>3)&7)*36;
778
+                r= (i&7     )*36;
779
+            } else if(c->srcFormat == PIX_FMT_RGB4_BYTE) {
780
+                r= (i>>3    )*255;
781
+                g= ((i>>1)&3)*85;
782
+                b= (i&1     )*255;
783
+            } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_Y400A) {
784
+                r = g = b = i;
785
+            } else {
786
+                assert(c->srcFormat == PIX_FMT_BGR4_BYTE);
787
+                b= (i>>3    )*255;
788
+                g= ((i>>1)&3)*85;
789
+                r= (i&1     )*255;
790
+            }
791
+            y= av_clip_uint8((RY*r + GY*g + BY*b + ( 33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
792
+            u= av_clip_uint8((RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
793
+            v= av_clip_uint8((RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
794
+            c->pal_yuv[i]= y + (u<<8) + (v<<16);
795
+
796
+            switch(c->dstFormat) {
797
+            case PIX_FMT_BGR32:
798
+#if !HAVE_BIGENDIAN
799
+            case PIX_FMT_RGB24:
800
+#endif
801
+                c->pal_rgb[i]=  r + (g<<8) + (b<<16);
802
+                break;
803
+            case PIX_FMT_BGR32_1:
804
+#if HAVE_BIGENDIAN
805
+            case PIX_FMT_BGR24:
806
+#endif
807
+                c->pal_rgb[i]= (r + (g<<8) + (b<<16)) << 8;
808
+                break;
809
+            case PIX_FMT_RGB32_1:
810
+#if HAVE_BIGENDIAN
811
+            case PIX_FMT_RGB24:
812
+#endif
813
+                c->pal_rgb[i]= (b + (g<<8) + (r<<16)) << 8;
814
+                break;
815
+            case PIX_FMT_RGB32:
816
+#if !HAVE_BIGENDIAN
817
+            case PIX_FMT_BGR24:
818
+#endif
819
+            default:
820
+                c->pal_rgb[i]=  b + (g<<8) + (r<<16);
821
+            }
822
+        }
823
+    }
824
+
825
+    // copy strides, so they can safely be modified
826
+    if (c->sliceDir == 1) {
827
+        // slices go from top to bottom
828
+        int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2], srcStride[3]};
829
+        int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]};
830
+
831
+        reset_ptr(src2, c->srcFormat);
832
+        reset_ptr((const uint8_t**)dst2, c->dstFormat);
833
+
834
+        /* reset slice direction at end of frame */
835
+        if (srcSliceY + srcSliceH == c->srcH)
836
+            c->sliceDir = 0;
837
+
838
+        return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, dstStride2);
839
+    } else {
840
+        // slices go from bottom to top => we flip the image internally
841
+        int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2], -srcStride[3]};
842
+        int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2], -dstStride[3]};
843
+
844
+        src2[0] += (srcSliceH-1)*srcStride[0];
845
+        if (!usePal(c->srcFormat))
846
+            src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1];
847
+        src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2];
848
+        src2[3] += (srcSliceH-1)*srcStride[3];
849
+        dst2[0] += ( c->dstH                      -1)*dstStride[0];
850
+        dst2[1] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1];
851
+        dst2[2] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2];
852
+        dst2[3] += ( c->dstH                      -1)*dstStride[3];
853
+
854
+        reset_ptr(src2, c->srcFormat);
855
+        reset_ptr((const uint8_t**)dst2, c->dstFormat);
856
+
857
+        /* reset slice direction at end of frame */
858
+        if (!srcSliceY)
859
+            c->sliceDir = 0;
860
+
861
+        return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2);
862
+    }
863
+}
864
+
865
+/* Convert the palette to the same packed 32-bit format as the palette */
866
+void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
867
+{
868
+    int i;
869
+
870
+    for (i=0; i<num_pixels; i++)
871
+        ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
872
+}
873
+
874
+/* Palette format: ABCD -> dst format: ABC */
875
+void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
876
+{
877
+    int i;
878
+
879
+    for (i=0; i<num_pixels; i++) {
880
+        //FIXME slow?
881
+        dst[0]= palette[src[i]*4+0];
882
+        dst[1]= palette[src[i]*4+1];
883
+        dst[2]= palette[src[i]*4+2];
884
+        dst+= 3;
885
+    }
886
+}