Skip to content
Snippets Groups Projects
swscale.c 71.3 KiB
Newer Older
  • Learn to ignore specific revisions
  •  * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
     *
     * This file is part of FFmpeg.
     *
    
     * FFmpeg is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
    
     *
     * FFmpeg is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
    
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
    
     * You should have received a copy of the GNU Lesser General Public
     * License along with FFmpeg; if not, write to the Free Software
    
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    
      supported Input formats: YV12, I420/IYUV, YUY2, UYVY, BGR32, BGR32_1, BGR24, BGR16, BGR15, RGB32, RGB32_1, RGB24, Y8/Y800, YVU9/IF09, PAL8
    
      supported output formats: YV12, I420/IYUV, YUY2, UYVY, {BGR,RGB}{1,4,8,15,16,24,32}, Y8/Y800, YVU9/IF09
    
      unscaled special converters (YV12=I420=IYUV, Y800=Y8)
    
      YV12 -> {BGR,RGB}{1,4,8,12,15,16,24,32}
    
      x -> x
      YUV9 -> YV12
      YUV9/YV12 -> Y800
      Y800 -> YUV9/YV12
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
      BGR24 -> BGR32 & RGB24 -> RGB32
      BGR32 -> BGR24 & RGB32 -> RGB24
    
      BGR15 -> BGR16
    
    Diego Biurrun's avatar
    Diego Biurrun committed
    tested special converters (most are tested actually, but I did not write it down ...)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
     YV12 -> YV12
    
     BGR15 -> BGR16
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    
    untested special converters
    
      YV12/I420 -> BGR15/BGR24/BGR32 (it is the yuv2rgb stuff, so it should be OK)
    
      YV12/I420 -> YV12/I420
      YUY2/BGR15/BGR24/BGR32/RGB24/RGB32 -> same format
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
      BGR24 -> BGR32 & RGB24 -> RGB32
      BGR32 -> BGR24 & RGB32 -> RGB24
    
      BGR24 -> YV12
    
    #include <string.h>
    
    #include <math.h>
    
    #include <stdio.h>
    
    #include "config.h"
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #include <assert.h>
    
    #include "libavutil/intreadwrite.h"
    
    #include "libavutil/x86_cpu.h"
    
    #include "libavutil/avutil.h"
    
    #include "libavutil/mathematics.h"
    
    #include "libavutil/bswap.h"
    
    #include "libavutil/pixdesc.h"
    
    Arpi's avatar
    Arpi committed
    
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #undef MOVNTQ
    
    #undef PAVGB
    
    #define FAST_BGR2YV12 // use 7 bit coefficients instead of 15 bit
    
    #define isPacked(x)         (       \
               (x)==PIX_FMT_PAL8        \
            || (x)==PIX_FMT_YUYV422     \
            || (x)==PIX_FMT_UYVY422     \
    
            || isAnyRGB(x)              \
    
    #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
    #define BV (-(int)(0.081*224/255*(1<<RGB2YUV_SHIFT)+0.5))
    #define BU ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
    #define GY ( (int)(0.587*219/255*(1<<RGB2YUV_SHIFT)+0.5))
    #define GV (-(int)(0.419*224/255*(1<<RGB2YUV_SHIFT)+0.5))
    #define GU (-(int)(0.331*224/255*(1<<RGB2YUV_SHIFT)+0.5))
    #define RY ( (int)(0.299*219/255*(1<<RGB2YUV_SHIFT)+0.5))
    #define RV ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
    #define RU (-(int)(0.169*224/255*(1<<RGB2YUV_SHIFT)+0.5))
    
    static const double rgb2yuv_table[8][9]={
    
        {0.7152, 0.0722, 0.2126, -0.386, 0.5, -0.115, -0.454, -0.046, 0.5}, //ITU709
        {0.7152, 0.0722, 0.2126, -0.386, 0.5, -0.115, -0.454, -0.046, 0.5}, //ITU709
        {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
        {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
    
        {0.59  , 0.11  , 0.30  , -0.331, 0.5, -0.169, -0.421, -0.079, 0.5}, //FCC
    
        {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
        {0.587 , 0.114 , 0.299 , -0.331, 0.5, -0.169, -0.419, -0.081, 0.5}, //DEFAULT / ITU601 / ITU624 / SMPTE 170M
    
        {0.701 , 0.087 , 0.212 , -0.384, 0.5, -0.116, -0.445, -0.055, 0.5}, //SMPTE 240M
    
    Special versions: fast Y 1:1 scaling (no interpolation in y direction)
    
    Diego Biurrun's avatar
    Diego Biurrun committed
    more intelligent misalignment avoidance for the horizontal scaler
    
    write special vertical cubic upscale version
    
    optimize C code (YV12 / minmax)
    add support for packed pixel YUV input & output
    
    add support for Y8 output
    
    optimize BGR24 & BGR32
    
    write special BGR->BGR scaler
    
    DECLARE_ASM_CONST(8, uint64_t, bF8)=       0xF8F8F8F8F8F8F8F8LL;
    DECLARE_ASM_CONST(8, uint64_t, bFC)=       0xFCFCFCFCFCFCFCFCLL;
    DECLARE_ASM_CONST(8, uint64_t, w10)=       0x0010001000100010LL;
    DECLARE_ASM_CONST(8, uint64_t, w02)=       0x0002000200020002LL;
    DECLARE_ASM_CONST(8, uint64_t, bm00001111)=0x00000000FFFFFFFFLL;
    DECLARE_ASM_CONST(8, uint64_t, bm00000111)=0x0000000000FFFFFFLL;
    DECLARE_ASM_CONST(8, uint64_t, bm11111000)=0xFFFFFFFFFF000000LL;
    DECLARE_ASM_CONST(8, uint64_t, bm01010101)=0x00FF00FF00FF00FFLL;
    
    const DECLARE_ALIGNED(8, uint64_t, ff_dither4)[2] = {
    
            0x0103010301030103LL,
            0x0200020002000200LL,};
    
    const DECLARE_ALIGNED(8, uint64_t, ff_dither8)[2] = {
    
            0x0602060206020602LL,
            0x0004000400040004LL,};
    
    DECLARE_ASM_CONST(8, uint64_t, b16Mask)=   0x001F001F001F001FLL;
    DECLARE_ASM_CONST(8, uint64_t, g16Mask)=   0x07E007E007E007E0LL;
    DECLARE_ASM_CONST(8, uint64_t, r16Mask)=   0xF800F800F800F800LL;
    DECLARE_ASM_CONST(8, uint64_t, b15Mask)=   0x001F001F001F001FLL;
    DECLARE_ASM_CONST(8, uint64_t, g15Mask)=   0x03E003E003E003E0LL;
    DECLARE_ASM_CONST(8, uint64_t, r15Mask)=   0x7C007C007C007C00LL;
    
    DECLARE_ALIGNED(8, const uint64_t, ff_M24A)         = 0x00FF0000FF0000FFLL;
    DECLARE_ALIGNED(8, const uint64_t, ff_M24B)         = 0xFF0000FF0000FF00LL;
    DECLARE_ALIGNED(8, const uint64_t, ff_M24C)         = 0x0000FF0000FF0000LL;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #ifdef FAST_BGR2YV12
    
    DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YCoeff)   = 0x000000210041000DULL;
    DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UCoeff)   = 0x0000FFEEFFDC0038ULL;
    DECLARE_ALIGNED(8, const uint64_t, ff_bgr2VCoeff)   = 0x00000038FFD2FFF8ULL;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
    #else
    
    DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YCoeff)   = 0x000020E540830C8BULL;
    DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UCoeff)   = 0x0000ED0FDAC23831ULL;
    DECLARE_ALIGNED(8, const uint64_t, ff_bgr2VCoeff)   = 0x00003831D0E6F6EAULL;
    
    #endif /* FAST_BGR2YV12 */
    
    DECLARE_ALIGNED(8, const uint64_t, ff_bgr2YOffset)  = 0x1010101010101010ULL;
    DECLARE_ALIGNED(8, const uint64_t, ff_bgr2UVOffset) = 0x8080808080808080ULL;
    DECLARE_ALIGNED(8, const uint64_t, ff_w1111)        = 0x0001000100010001ULL;
    
    DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toY1Coeff) = 0x0C88000040870C88ULL;
    DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toY2Coeff) = 0x20DE4087000020DEULL;
    DECLARE_ASM_CONST(8, uint64_t, ff_rgb24toY1Coeff) = 0x20DE0000408720DEULL;
    DECLARE_ASM_CONST(8, uint64_t, ff_rgb24toY2Coeff) = 0x0C88408700000C88ULL;
    DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toYOffset) = 0x0008400000084000ULL;
    
    DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toUV)[2][4] = {
    
        {0x38380000DAC83838ULL, 0xECFFDAC80000ECFFULL, 0xF6E40000D0E3F6E4ULL, 0x3838D0E300003838ULL},
        {0xECFF0000DAC8ECFFULL, 0x3838DAC800003838ULL, 0x38380000D0E33838ULL, 0xF6E4D0E30000F6E4ULL},
    };
    
    
    DECLARE_ASM_CONST(8, uint64_t, ff_bgr24toUVOffset)= 0x0040400000404000ULL;
    
    DECLARE_ALIGNED(8, static const uint8_t, dither_2x2_4)[2][8]={
    
    {  1,   3,   1,   3,   1,   3,   1,   3, },
    {  2,   0,   2,   0,   2,   0,   2,   0, },
    };
    
    
    DECLARE_ALIGNED(8, static const uint8_t, dither_2x2_8)[2][8]={
    
    {  6,   2,   6,   2,   6,   2,   6,   2, },
    {  0,   4,   0,   4,   0,   4,   0,   4, },
    };
    
    
    DECLARE_ALIGNED(8, const uint8_t, dither_4x4_16)[4][8]={
    {  8,   4,  11,   7,   8,   4,  11,   7, },
    {  2,  14,   1,  13,   2,  14,   1,  13, },
    { 10,   6,   9,   5,  10,   6,   9,   5, },
    {  0,  12,   3,  15,   0,  12,   3,  15, },
    };
    
    
    DECLARE_ALIGNED(8, const uint8_t, dither_8x8_32)[8][8]={
    
    { 17,   9,  23,  15,  16,   8,  22,  14, },
    {  5,  29,   3,  27,   4,  28,   2,  26, },
    { 21,  13,  19,  11,  20,  12,  18,  10, },
    {  0,  24,   6,  30,   1,  25,   7,  31, },
    { 16,   8,  22,  14,  17,   9,  23,  15, },
    {  4,  28,   2,  26,   5,  29,   3,  27, },
    { 20,  12,  18,  10,  21,  13,  19,  11, },
    {  1,  25,   7,  31,   0,  24,   6,  30, },
    };
    
    
    DECLARE_ALIGNED(8, const uint8_t, dither_8x8_73)[8][8]={
    
    {  0,  55,  14,  68,   3,  58,  17,  72, },
    { 37,  18,  50,  32,  40,  22,  54,  35, },
    {  9,  64,   5,  59,  13,  67,   8,  63, },
    { 46,  27,  41,  23,  49,  31,  44,  26, },
    {  2,  57,  16,  71,   1,  56,  15,  70, },
    { 39,  21,  52,  34,  38,  19,  51,  33, },
    { 11,  66,   7,  62,  10,  65,   6,  60, },
    { 48,  30,  43,  25,  47,  29,  42,  24, },
    };
    
    #if 1
    
    DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
    
    {117,  62, 158, 103, 113,  58, 155, 100, },
    { 34, 199,  21, 186,  31, 196,  17, 182, },
    {144,  89, 131,  76, 141,  86, 127,  72, },
    {  0, 165,  41, 206,  10, 175,  52, 217, },
    {110,  55, 151,  96, 120,  65, 162, 107, },
    { 28, 193,  14, 179,  38, 203,  24, 189, },
    {138,  83, 124,  69, 148,  93, 134,  79, },
    {  7, 172,  48, 213,   3, 168,  45, 210, },
    };
    #elif 1
    // tries to correct a gamma of 1.5
    
    DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
    
    {  0, 143,  18, 200,   2, 156,  25, 215, },
    { 78,  28, 125,  64,  89,  36, 138,  74, },
    { 10, 180,   3, 161,  16, 195,   8, 175, },
    {109,  51,  93,  38, 121,  60, 105,  47, },
    {  1, 152,  23, 210,   0, 147,  20, 205, },
    { 85,  33, 134,  71,  81,  30, 130,  67, },
    { 14, 190,   6, 171,  12, 185,   5, 166, },
    {117,  57, 101,  44, 113,  54,  97,  41, },
    };
    #elif 1
    // tries to correct a gamma of 2.0
    
    DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
    
    {  0, 124,   8, 193,   0, 140,  12, 213, },
    { 55,  14, 104,  42,  66,  19, 119,  52, },
    {  3, 168,   1, 145,   6, 187,   3, 162, },
    { 86,  31,  70,  21,  99,  39,  82,  28, },
    {  0, 134,  11, 206,   0, 129,   9, 200, },
    { 62,  17, 114,  48,  58,  16, 109,  45, },
    {  5, 181,   2, 157,   4, 175,   1, 151, },
    { 95,  36,  78,  26,  90,  34,  74,  24, },
    };
    #else
    // tries to correct a gamma of 2.5
    
    DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
    
    {  0, 107,   3, 187,   0, 125,   6, 212, },
    { 39,   7,  86,  28,  49,  11, 102,  36, },
    {  1, 158,   0, 131,   3, 180,   1, 151, },
    { 68,  19,  52,  12,  81,  25,  64,  17, },
    {  0, 119,   5, 203,   0, 113,   4, 195, },
    { 45,   9,  96,  33,  42,   8,  91,  30, },
    {  2, 172,   1, 144,   2, 165,   0, 137, },
    { 77,  23,  60,  15,  72,  21,  56,  14, },
    };
    #endif
    
    static av_always_inline void yuv2yuvX16inC_template(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
                                                        const int16_t *chrFilter, const int16_t **chrSrc, int chrFilterSize,
                                                        const int16_t **alpSrc, uint16_t *dest, uint16_t *uDest, uint16_t *vDest, uint16_t *aDest,
                                                        int dstW, int chrDstW, int big_endian)
    {
        //FIXME Optimize (just quickly written not optimized..)
        int i;
    
        for (i = 0; i < dstW; i++) {
            int val = 1 << 10;
            int j;
    
            for (j = 0; j < lumFilterSize; j++)
                val += lumSrc[j][i] * lumFilter[j];
    
            if (big_endian) {
                AV_WB16(&dest[i], av_clip_uint16(val >> 11));
            } else {
                AV_WL16(&dest[i], av_clip_uint16(val >> 11));
            }
        }
    
        if (uDest) {
            for (i = 0; i < chrDstW; i++) {
                int u = 1 << 10;
                int v = 1 << 10;
                int j;
    
                for (j = 0; j < chrFilterSize; j++) {
                    u += chrSrc[j][i       ] * chrFilter[j];
                    v += chrSrc[j][i + VOFW] * chrFilter[j];
                }
    
                if (big_endian) {
                    AV_WB16(&uDest[i], av_clip_uint16(u >> 11));
                    AV_WB16(&vDest[i], av_clip_uint16(v >> 11));
                } else {
                    AV_WL16(&uDest[i], av_clip_uint16(u >> 11));
                    AV_WL16(&vDest[i], av_clip_uint16(v >> 11));
                }
            }
        }
    
        if (CONFIG_SWSCALE_ALPHA && aDest) {
            for (i = 0; i < dstW; i++) {
                int val = 1 << 10;
                int j;
    
                for (j = 0; j < lumFilterSize; j++)
                    val += alpSrc[j][i] * lumFilter[j];
    
                if (big_endian) {
                    AV_WB16(&aDest[i], av_clip_uint16(val >> 11));
                } else {
                    AV_WL16(&aDest[i], av_clip_uint16(val >> 11));
                }
            }
        }
    }
    
    static inline void yuv2yuvX16inC(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
                                     const int16_t *chrFilter, const int16_t **chrSrc, int chrFilterSize,
                                     const int16_t **alpSrc, uint16_t *dest, uint16_t *uDest, uint16_t *vDest, uint16_t *aDest, int dstW, int chrDstW,
                                     enum PixelFormat dstFormat)
    {
        if (isBE(dstFormat)) {
            yuv2yuvX16inC_template(lumFilter, lumSrc, lumFilterSize,
                                   chrFilter, chrSrc, chrFilterSize,
                                   alpSrc,
                                   dest, uDest, vDest, aDest,
                                   dstW, chrDstW, 1);
        } else {
            yuv2yuvX16inC_template(lumFilter, lumSrc, lumFilterSize,
                                   chrFilter, chrSrc, chrFilterSize,
                                   alpSrc,
                                   dest, uDest, vDest, aDest,
                                   dstW, chrDstW, 0);
        }
    }
    
    
    static inline void yuv2yuvXinC(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
                                   const int16_t *chrFilter, const int16_t **chrSrc, int chrFilterSize,
                                   const int16_t **alpSrc, uint8_t *dest, uint8_t *uDest, uint8_t *vDest, uint8_t *aDest, int dstW, int chrDstW)
    
        //FIXME Optimize (just quickly written not optimized..)
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<dstW; i++) {
    
            int val=1<<18;
            int j;
            for (j=0; j<lumFilterSize; j++)
                val += lumSrc[j][i] * lumFilter[j];
    
            dest[i]= av_clip_uint8(val>>19);
        }
    
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (i=0; i<chrDstW; i++) {
    
    Ramiro Polla's avatar
    Ramiro Polla committed
                for (j=0; j<chrFilterSize; j++) {
    
                    v += chrSrc[j][i + VOFW] * chrFilter[j];
    
                }
    
                uDest[i]= av_clip_uint8(u>>19);
                vDest[i]= av_clip_uint8(v>>19);
            }
    
    
        if (CONFIG_SWSCALE_ALPHA && aDest)
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (i=0; i<dstW; i++) {
    
                int val=1<<18;
                int j;
                for (j=0; j<lumFilterSize; j++)
                    val += alpSrc[j][i] * lumFilter[j];
    
                aDest[i]= av_clip_uint8(val>>19);
            }
    
    
    static inline void yuv2nv12XinC(const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
                                    const int16_t *chrFilter, const int16_t **chrSrc, int chrFilterSize,
    
                                    uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat)
    
        //FIXME Optimize (just quickly written not optimized..)
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<dstW; i++) {
    
            int val=1<<18;
            int j;
            for (j=0; j<lumFilterSize; j++)
                val += lumSrc[j][i] * lumFilter[j];
    
            dest[i]= av_clip_uint8(val>>19);
        }
    
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (i=0; i<chrDstW; i++) {
    
    Ramiro Polla's avatar
    Ramiro Polla committed
                for (j=0; j<chrFilterSize; j++) {
    
                    v += chrSrc[j][i + VOFW] * chrFilter[j];
    
                }
    
                uDest[2*i]= av_clip_uint8(u>>19);
                uDest[2*i+1]= av_clip_uint8(v>>19);
            }
        else
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (i=0; i<chrDstW; i++) {
    
    Ramiro Polla's avatar
    Ramiro Polla committed
                for (j=0; j<chrFilterSize; j++) {
    
                    v += chrSrc[j][i + VOFW] * chrFilter[j];
    
                }
    
                uDest[2*i]= av_clip_uint8(v>>19);
                uDest[2*i+1]= av_clip_uint8(u>>19);
            }
    
    #define YSCALE_YUV_2_PACKEDX_NOCLIP_C(type,alpha) \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<(dstW>>1); i++) {\
    
            int j;\
            int Y1 = 1<<18;\
            int Y2 = 1<<18;\
            int U  = 1<<18;\
            int V  = 1<<18;\
    
            int av_unused A1, A2;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (j=0; j<lumFilterSize; j++) {\
    
                Y1 += lumSrc[j][i2] * lumFilter[j];\
                Y2 += lumSrc[j][i2+1] * lumFilter[j];\
            }\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (j=0; j<chrFilterSize; j++) {\
    
                V += chrSrc[j][i+VOFW] * chrFilter[j];\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (alpha) {\
    
                A1 = 1<<18;\
                A2 = 1<<18;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
                for (j=0; j<lumFilterSize; j++) {\
    
                    A1 += alpSrc[j][i2  ] * lumFilter[j];\
                    A2 += alpSrc[j][i2+1] * lumFilter[j];\
                }\
                A1>>=19;\
                A2>>=19;\
    
    #define YSCALE_YUV_2_PACKEDX_C(type,alpha) \
            YSCALE_YUV_2_PACKEDX_NOCLIP_C(type,alpha)\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if ((Y1|Y2|U|V)&256) {\
    
                if (Y1>255)   Y1=255; \
                else if (Y1<0)Y1=0;   \
                if (Y2>255)   Y2=255; \
                else if (Y2<0)Y2=0;   \
                if (U>255)    U=255;  \
                else if (U<0) U=0;    \
                if (V>255)    V=255;  \
                else if (V<0) V=0;    \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (alpha && ((A1|A2)&256)) {\
    
                A1=av_clip_uint8(A1);\
                A2=av_clip_uint8(A2);\
    
    #define YSCALE_YUV_2_PACKEDX_FULL_C(rnd,alpha) \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<dstW; i++) {\
    
            int j;\
            int Y = 0;\
            int U = -128<<19;\
            int V = -128<<19;\
    
            int av_unused A;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (j=0; j<lumFilterSize; j++) {\
    
                Y += lumSrc[j][i     ] * lumFilter[j];\
            }\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (j=0; j<chrFilterSize; j++) {\
    
                U += chrSrc[j][i     ] * chrFilter[j];\
                V += chrSrc[j][i+VOFW] * chrFilter[j];\
            }\
            Y >>=10;\
            U >>=10;\
            V >>=10;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (alpha) {\
    
                A = rnd;\
                for (j=0; j<lumFilterSize; j++)\
                    A += alpSrc[j][i     ] * lumFilter[j];\
                A >>=19;\
                if (A&256)\
                    A = av_clip_uint8(A);\
    
    #define YSCALE_YUV_2_RGBX_FULL_C(rnd,alpha) \
        YSCALE_YUV_2_PACKEDX_FULL_C(rnd>>3,alpha)\
    
            Y-= c->yuv2rgb_y_offset;\
            Y*= c->yuv2rgb_y_coeff;\
    
            R= Y + V*c->yuv2rgb_v2r_coeff;\
            G= Y + V*c->yuv2rgb_v2g_coeff + U*c->yuv2rgb_u2g_coeff;\
            B= Y +                          U*c->yuv2rgb_u2b_coeff;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if ((R|G|B)&(0xC0000000)) {\
    
                if (R>=(256<<22))   R=(256<<22)-1; \
                else if (R<0)R=0;   \
                if (G>=(256<<22))   G=(256<<22)-1; \
                else if (G<0)G=0;   \
                if (B>=(256<<22))   B=(256<<22)-1; \
                else if (B<0)B=0;   \
    
    #define YSCALE_YUV_2_GRAY16_C \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<(dstW>>1); i++) {\
    
            int j;\
            int Y1 = 1<<18;\
            int Y2 = 1<<18;\
            int U  = 1<<18;\
            int V  = 1<<18;\
    
            const int i2= 2*i;\
            \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (j=0; j<lumFilterSize; j++) {\
    
                Y1 += lumSrc[j][i2] * lumFilter[j];\
                Y2 += lumSrc[j][i2+1] * lumFilter[j];\
            }\
            Y1>>=11;\
            Y2>>=11;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if ((Y1|Y2|U|V)&65536) {\
    
                if (Y1>65535)   Y1=65535; \
                else if (Y1<0)Y1=0;   \
                if (Y2>65535)   Y2=65535; \
                else if (Y2<0)Y2=0;   \
            }
    
    
    #define YSCALE_YUV_2_RGBX_C(type,alpha) \
        YSCALE_YUV_2_PACKEDX_C(type,alpha)  /* FIXME fix tables so that clipping is not needed and then use _NOCLIP*/\
    
        r = (type *)c->table_rV[V];   \
        g = (type *)(c->table_gU[U] + c->table_gV[V]); \
    
        b = (type *)c->table_bU[U];
    
    #define YSCALE_YUV_2_PACKED2_C(type,alpha)   \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<(dstW>>1); i++) { \
    
            const int i2= 2*i;       \
            int Y1= (buf0[i2  ]*yalpha1+buf1[i2  ]*yalpha)>>19;           \
            int Y2= (buf0[i2+1]*yalpha1+buf1[i2+1]*yalpha)>>19;           \
            int U= (uvbuf0[i     ]*uvalpha1+uvbuf1[i     ]*uvalpha)>>19;  \
    
            int V= (uvbuf0[i+VOFW]*uvalpha1+uvbuf1[i+VOFW]*uvalpha)>>19;  \
    
            type av_unused *r, *b, *g;                                    \
            int av_unused A1, A2;                                         \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (alpha) {\
    
                A1= (abuf0[i2  ]*yalpha1+abuf1[i2  ]*yalpha)>>19;         \
                A2= (abuf0[i2+1]*yalpha1+abuf1[i2+1]*yalpha)>>19;         \
    
    #define YSCALE_YUV_2_GRAY16_2_C   \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<(dstW>>1); i++) { \
    
            const int i2= 2*i;       \
            int Y1= (buf0[i2  ]*yalpha1+buf1[i2  ]*yalpha)>>11;           \
    
            int Y2= (buf0[i2+1]*yalpha1+buf1[i2+1]*yalpha)>>11;
    
    #define YSCALE_YUV_2_RGB2_C(type,alpha) \
        YSCALE_YUV_2_PACKED2_C(type,alpha)\
    
        r = (type *)c->table_rV[V];\
        g = (type *)(c->table_gU[U] + c->table_gV[V]);\
    
        b = (type *)c->table_bU[U];
    
    #define YSCALE_YUV_2_PACKED1_C(type,alpha) \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<(dstW>>1); i++) {\
    
            const int i2= 2*i;\
            int Y1= buf0[i2  ]>>7;\
            int Y2= buf0[i2+1]>>7;\
            int U= (uvbuf1[i     ])>>7;\
    
            type av_unused *r, *b, *g;\
            int av_unused A1, A2;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (alpha) {\
    
                A1= abuf0[i2  ]>>7;\
                A2= abuf0[i2+1]>>7;\
    
    #define YSCALE_YUV_2_GRAY16_1_C \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<(dstW>>1); i++) {\
    
            const int i2= 2*i;\
            int Y1= buf0[i2  ]<<1;\
    
            int Y2= buf0[i2+1]<<1;
    
    #define YSCALE_YUV_2_RGB1_C(type,alpha) \
        YSCALE_YUV_2_PACKED1_C(type,alpha)\
    
        r = (type *)c->table_rV[V];\
        g = (type *)(c->table_gU[U] + c->table_gV[V]);\
    
        b = (type *)c->table_bU[U];
    
    #define YSCALE_YUV_2_PACKED1B_C(type,alpha) \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<(dstW>>1); i++) {\
    
            const int i2= 2*i;\
            int Y1= buf0[i2  ]>>7;\
            int Y2= buf0[i2+1]>>7;\
            int U= (uvbuf0[i     ] + uvbuf1[i     ])>>8;\
    
            int V= (uvbuf0[i+VOFW] + uvbuf1[i+VOFW])>>8;\
    
            type av_unused *r, *b, *g;\
            int av_unused A1, A2;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (alpha) {\
    
                A1= abuf0[i2  ]>>7;\
                A2= abuf0[i2+1]>>7;\
    
    #define YSCALE_YUV_2_RGB1B_C(type,alpha) \
        YSCALE_YUV_2_PACKED1B_C(type,alpha)\
    
        r = (type *)c->table_rV[V];\
        g = (type *)(c->table_gU[U] + c->table_gV[V]);\
    
        b = (type *)c->table_bU[U];
    
    #define YSCALE_YUV_2_MONO2_C \
    
        const uint8_t * const d128=dither_8x8_220[y&7];\
        uint8_t *g= c->table_gU[128] + c->table_gV[128];\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<dstW-7; i+=8) {\
    
            int acc;\
            acc =       g[((buf0[i  ]*yalpha1+buf1[i  ]*yalpha)>>19) + d128[0]];\
            acc+= acc + g[((buf0[i+1]*yalpha1+buf1[i+1]*yalpha)>>19) + d128[1]];\
            acc+= acc + g[((buf0[i+2]*yalpha1+buf1[i+2]*yalpha)>>19) + d128[2]];\
            acc+= acc + g[((buf0[i+3]*yalpha1+buf1[i+3]*yalpha)>>19) + d128[3]];\
            acc+= acc + g[((buf0[i+4]*yalpha1+buf1[i+4]*yalpha)>>19) + d128[4]];\
            acc+= acc + g[((buf0[i+5]*yalpha1+buf1[i+5]*yalpha)>>19) + d128[5]];\
            acc+= acc + g[((buf0[i+6]*yalpha1+buf1[i+6]*yalpha)>>19) + d128[6]];\
            acc+= acc + g[((buf0[i+7]*yalpha1+buf1[i+7]*yalpha)>>19) + d128[7]];\
    
            ((uint8_t*)dest)[0]= c->dstFormat == PIX_FMT_MONOBLACK ? acc : ~acc;\
    
    #define YSCALE_YUV_2_MONOX_C \
    
        const uint8_t * const d128=dither_8x8_220[y&7];\
        uint8_t *g= c->table_gU[128] + c->table_gV[128];\
        int acc=0;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<dstW-1; i+=2) {\
    
            int j;\
            int Y1=1<<18;\
            int Y2=1<<18;\
    \
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            for (j=0; j<lumFilterSize; j++) {\
    
                Y1 += lumSrc[j][i] * lumFilter[j];\
                Y2 += lumSrc[j][i+1] * lumFilter[j];\
            }\
            Y1>>=19;\
            Y2>>=19;\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if ((Y1|Y2)&256) {\
    
                if (Y1>255)   Y1=255;\
                else if (Y1<0)Y1=0;\
                if (Y2>255)   Y2=255;\
                else if (Y2<0)Y2=0;\
            }\
            acc+= acc + g[Y1+d128[(i+0)&7]];\
            acc+= acc + g[Y2+d128[(i+1)&7]];\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if ((i&7)==6) {\
    
                ((uint8_t*)dest)[0]= c->dstFormat == PIX_FMT_MONOBLACK ? acc : ~acc;\
    
                dest++;\
            }\
        }
    
    #define YSCALE_YUV_2_ANYRGB_C(func, func2, func_g16, func_monoblack)\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        switch(c->dstFormat) {\
    
        case PIX_FMT_RGB48BE:\
        case PIX_FMT_RGB48LE:\
            func(uint8_t,0)\
                ((uint8_t*)dest)[ 0]= r[Y1];\
                ((uint8_t*)dest)[ 1]= r[Y1];\
                ((uint8_t*)dest)[ 2]= g[Y1];\
                ((uint8_t*)dest)[ 3]= g[Y1];\
                ((uint8_t*)dest)[ 4]= b[Y1];\
                ((uint8_t*)dest)[ 5]= b[Y1];\
                ((uint8_t*)dest)[ 6]= r[Y2];\
                ((uint8_t*)dest)[ 7]= r[Y2];\
                ((uint8_t*)dest)[ 8]= g[Y2];\
                ((uint8_t*)dest)[ 9]= g[Y2];\
                ((uint8_t*)dest)[10]= b[Y2];\
                ((uint8_t*)dest)[11]= b[Y2];\
                dest+=12;\
            }\
            break;\
    
        case PIX_FMT_RGBA:\
        case PIX_FMT_BGRA:\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (CONFIG_SMALL) {\
    
                int needAlpha = CONFIG_SWSCALE_ALPHA && c->alpPixBuf;\
                func(uint32_t,needAlpha)\
                    ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1] + (needAlpha ? (A1<<24) : 0);\
                    ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2] + (needAlpha ? (A2<<24) : 0);\
                }\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            } else {\
                if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {\
    
                    func(uint32_t,1)\
                        ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1] + (A1<<24);\
                        ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2] + (A2<<24);\
                    }\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
                } else {\
    
                    func(uint32_t,0)\
                        ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\
                        ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\
                    }\
                }\
            }\
            break;\
        case PIX_FMT_ARGB:\
        case PIX_FMT_ABGR:\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (CONFIG_SMALL) {\
    
                int needAlpha = CONFIG_SWSCALE_ALPHA && c->alpPixBuf;\
                func(uint32_t,needAlpha)\
                    ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1] + (needAlpha ? A1 : 0);\
                    ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2] + (needAlpha ? A2 : 0);\
                }\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            } else {\
                if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {\
    
                    func(uint32_t,1)\
                        ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1] + A1;\
                        ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2] + A2;\
                    }\
    
    Ramiro Polla's avatar
    Ramiro Polla committed
                } else {\
    
                    func(uint32_t,0)\
                        ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\
                        ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\
                    }\
                }\
    
            func(uint8_t,0)\
    
                ((uint8_t*)dest)[0]= r[Y1];\
                ((uint8_t*)dest)[1]= g[Y1];\
                ((uint8_t*)dest)[2]= b[Y1];\
                ((uint8_t*)dest)[3]= r[Y2];\
                ((uint8_t*)dest)[4]= g[Y2];\
                ((uint8_t*)dest)[5]= b[Y2];\
                dest+=6;\
            }\
            break;\
        case PIX_FMT_BGR24:\
    
            func(uint8_t,0)\
    
                ((uint8_t*)dest)[0]= b[Y1];\
                ((uint8_t*)dest)[1]= g[Y1];\
                ((uint8_t*)dest)[2]= r[Y1];\
                ((uint8_t*)dest)[3]= b[Y2];\
                ((uint8_t*)dest)[4]= g[Y2];\
                ((uint8_t*)dest)[5]= r[Y2];\
                dest+=6;\
            }\
            break;\
    
        case PIX_FMT_RGB565BE:\
        case PIX_FMT_RGB565LE:\
        case PIX_FMT_BGR565BE:\
        case PIX_FMT_BGR565LE:\
    
            {\
                const int dr1= dither_2x2_8[y&1    ][0];\
                const int dg1= dither_2x2_4[y&1    ][0];\
                const int db1= dither_2x2_8[(y&1)^1][0];\
                const int dr2= dither_2x2_8[y&1    ][1];\
                const int dg2= dither_2x2_4[y&1    ][1];\
                const int db2= dither_2x2_8[(y&1)^1][1];\
    
                func(uint16_t,0)\
    
                    ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
                    ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
                }\
            }\
            break;\
    
        case PIX_FMT_RGB555BE:\
        case PIX_FMT_RGB555LE:\
        case PIX_FMT_BGR555BE:\
        case PIX_FMT_BGR555LE:\
    
            {\
                const int dr1= dither_2x2_8[y&1    ][0];\
                const int dg1= dither_2x2_8[y&1    ][1];\
                const int db1= dither_2x2_8[(y&1)^1][0];\
                const int dr2= dither_2x2_8[y&1    ][1];\
                const int dg2= dither_2x2_8[y&1    ][0];\
                const int db2= dither_2x2_8[(y&1)^1][1];\
    
                func(uint16_t,0)\
    
                    ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
                    ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
                }\
            }\
            break;\
    
        case PIX_FMT_RGB444BE:\
        case PIX_FMT_RGB444LE:\
        case PIX_FMT_BGR444BE:\
        case PIX_FMT_BGR444LE:\
            {\
                const int dr1= dither_4x4_16[y&3    ][0];\
                const int dg1= dither_4x4_16[y&3    ][1];\
                const int db1= dither_4x4_16[(y&3)^3][0];\
                const int dr2= dither_4x4_16[y&3    ][1];\
                const int dg2= dither_4x4_16[y&3    ][0];\
                const int db2= dither_4x4_16[(y&3)^3][1];\
                func(uint16_t,0)\
                    ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
                    ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
                }\
            }\
            break;\
    
        case PIX_FMT_RGB8:\
        case PIX_FMT_BGR8:\
            {\
                const uint8_t * const d64= dither_8x8_73[y&7];\
                const uint8_t * const d32= dither_8x8_32[y&7];\
    
                func(uint8_t,0)\
    
                    ((uint8_t*)dest)[i2+0]= r[Y1+d32[(i2+0)&7]] + g[Y1+d32[(i2+0)&7]] + b[Y1+d64[(i2+0)&7]];\
                    ((uint8_t*)dest)[i2+1]= r[Y2+d32[(i2+1)&7]] + g[Y2+d32[(i2+1)&7]] + b[Y2+d64[(i2+1)&7]];\
                }\
            }\
            break;\
        case PIX_FMT_RGB4:\
        case PIX_FMT_BGR4:\
            {\
                const uint8_t * const d64= dither_8x8_73 [y&7];\
                const uint8_t * const d128=dither_8x8_220[y&7];\
    
                func(uint8_t,0)\
    
                    ((uint8_t*)dest)[i]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]]\
                                     + ((r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]])<<4);\
                }\
            }\
            break;\
        case PIX_FMT_RGB4_BYTE:\
        case PIX_FMT_BGR4_BYTE:\
            {\
                const uint8_t * const d64= dither_8x8_73 [y&7];\
                const uint8_t * const d128=dither_8x8_220[y&7];\
    
                func(uint8_t,0)\
    
                    ((uint8_t*)dest)[i2+0]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]];\
                    ((uint8_t*)dest)[i2+1]= r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]];\
                }\
            }\
            break;\
        case PIX_FMT_MONOBLACK:\
    
                func_monoblack\
    
            }\
            break;\
        case PIX_FMT_YUYV422:\
            func2\
                ((uint8_t*)dest)[2*i2+0]= Y1;\
                ((uint8_t*)dest)[2*i2+1]= U;\
                ((uint8_t*)dest)[2*i2+2]= Y2;\
                ((uint8_t*)dest)[2*i2+3]= V;\
            }                \
            break;\
        case PIX_FMT_UYVY422:\
            func2\
                ((uint8_t*)dest)[2*i2+0]= U;\
                ((uint8_t*)dest)[2*i2+1]= Y1;\
                ((uint8_t*)dest)[2*i2+2]= V;\
                ((uint8_t*)dest)[2*i2+3]= Y2;\
            }                \
            break;\
    
        case PIX_FMT_GRAY16BE:\
            func_g16\
                ((uint8_t*)dest)[2*i2+0]= Y1>>8;\
                ((uint8_t*)dest)[2*i2+1]= Y1;\
                ((uint8_t*)dest)[2*i2+2]= Y2>>8;\
                ((uint8_t*)dest)[2*i2+3]= Y2;\
            }                \
            break;\
        case PIX_FMT_GRAY16LE:\
            func_g16\
                ((uint8_t*)dest)[2*i2+0]= Y1;\
                ((uint8_t*)dest)[2*i2+1]= Y1>>8;\
                ((uint8_t*)dest)[2*i2+2]= Y2;\
                ((uint8_t*)dest)[2*i2+3]= Y2>>8;\
            }                \
            break;\
    
    static inline void yuv2packedXinC(SwsContext *c, const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
                                      const int16_t *chrFilter, const int16_t **chrSrc, int chrFilterSize,
                                      const int16_t **alpSrc, uint8_t *dest, int dstW, int y)
    
        YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGBX_C, YSCALE_YUV_2_PACKEDX_C(void,0), YSCALE_YUV_2_GRAY16_C, YSCALE_YUV_2_MONOX_C)
    
    static inline void yuv2rgbXinC_full(SwsContext *c, const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,
                                        const int16_t *chrFilter, const int16_t **chrSrc, int chrFilterSize,
                                        const int16_t **alpSrc, uint8_t *dest, int dstW, int y)
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        switch(c->dstFormat) {
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (CONFIG_SMALL) {
    
                int needAlpha = CONFIG_SWSCALE_ALPHA && c->alpPixBuf;
                YSCALE_YUV_2_RGBX_FULL_C(1<<21, needAlpha)
                    dest[aidx]= needAlpha ? A : 255;
                    dest[0]= R>>22;
                    dest[1]= G>>22;
                    dest[2]= B>>22;
                    dest+= step;
                }
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            } else {
                if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
    
                    YSCALE_YUV_2_RGBX_FULL_C(1<<21, 1)
                        dest[aidx]= A;
                        dest[0]= R>>22;
                        dest[1]= G>>22;
                        dest[2]= B>>22;
                        dest+= step;
                    }
    
    Ramiro Polla's avatar
    Ramiro Polla committed
                } else {
    
                    YSCALE_YUV_2_RGBX_FULL_C(1<<21, 0)
                        dest[aidx]= 255;
                        dest[0]= R>>22;
                        dest[1]= G>>22;
                        dest[2]= B>>22;
                        dest+= step;
                    }
                }
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            if (CONFIG_SMALL) {
    
                int needAlpha = CONFIG_SWSCALE_ALPHA && c->alpPixBuf;
                YSCALE_YUV_2_RGBX_FULL_C(1<<21, needAlpha)
                    dest[aidx]= needAlpha ? A : 255;
                    dest[0]= B>>22;
                    dest[1]= G>>22;
                    dest[2]= R>>22;
                    dest+= step;
                }
    
    Ramiro Polla's avatar
    Ramiro Polla committed
            } else {
                if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
    
                    YSCALE_YUV_2_RGBX_FULL_C(1<<21, 1)
                        dest[aidx]= A;
                        dest[0]= B>>22;
                        dest[1]= G>>22;
                        dest[2]= R>>22;
                        dest+= step;
                    }
    
    Ramiro Polla's avatar
    Ramiro Polla committed
                } else {
    
                    YSCALE_YUV_2_RGBX_FULL_C(1<<21, 0)
                        dest[aidx]= 255;
                        dest[0]= B>>22;
                        dest[1]= G>>22;
                        dest[2]= R>>22;
                        dest+= step;
                    }
                }
    
    Ramiro Polla's avatar
    Ramiro Polla committed
    static void fillPlane(uint8_t* plane, int stride, int width, int height, int y, uint8_t val)
    {
    
        int i;
        uint8_t *ptr = plane + stride*y;
    
    Ramiro Polla's avatar
    Ramiro Polla committed
        for (i=0; i<height; i++) {
    
    static inline void rgb48ToY(uint8_t *dst, const uint8_t *src, long width,
    
    {
        int i;
        for (i = 0; i < width; i++) {
            int r = src[i*6+0];
            int g = src[i*6+2];
            int b = src[i*6+4];