X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libswscale%2Fswscale.c;h=b231302216ae11e240d083fc1fb07880b2f5be04;hb=92fed11352fae8855b44d99522c86cbfd323a6df;hp=2830f26ce553af8dafe5cba449d0d4a55651d473;hpb=42239ced656ddddb85eb9655e8a66d29065f0dad;p=ffmpeg diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 2830f26ce55..b231302216a 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -18,39 +18,6 @@ * 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 - {BGR,RGB}{1,4,8,15,16} support dithering - - 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 - BGR24 -> BGR32 & RGB24 -> RGB32 - BGR32 -> BGR24 & RGB32 -> RGB24 - BGR15 -> BGR16 -*/ - -/* -tested special converters (most are tested actually, but I did not write it down ...) - YV12 -> BGR12/BGR16 - YV12 -> YV12 - BGR15 -> BGR16 - BGR16 -> BGR16 - YVU9 -> YV12 - -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 - BGR24 -> BGR32 & RGB24 -> RGB32 - BGR32 -> BGR24 & RGB32 -> RGB24 - BGR24 -> YV12 -*/ - #include #include #include @@ -61,1994 +28,668 @@ untested special converters #include "swscale_internal.h" #include "rgb2rgb.h" #include "libavutil/intreadwrite.h" -#include "libavutil/x86_cpu.h" +#include "libavutil/cpu.h" #include "libavutil/avutil.h" #include "libavutil/mathematics.h" #include "libavutil/bswap.h" #include "libavutil/pixdesc.h" -#undef MOVNTQ -#undef PAVGB - -//#undef HAVE_MMX2 -//#define HAVE_AMD3DNOW -//#undef HAVE_MMX -//#undef ARCH_X86 -#define DITHER1XBPP - -#define isPacked(x) ( \ - (x)==PIX_FMT_PAL8 \ - || (x)==PIX_FMT_YUYV422 \ - || (x)==PIX_FMT_UYVY422 \ - || (x)==PIX_FMT_Y400A \ - || isAnyRGB(x) \ - ) - -#define RGB2YUV_SHIFT 15 -#define BY ( (int)(0.114*219/255*(1<BGR scaler -*/ - -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_128)[8][8] = { +{ 36, 68, 60, 92, 34, 66, 58, 90,}, +{ 100, 4,124, 28, 98, 2,122, 26,}, +{ 52, 84, 44, 76, 50, 82, 42, 74,}, +{ 116, 20,108, 12,114, 18,106, 10,}, +{ 32, 64, 56, 88, 38, 70, 62, 94,}, +{ 96, 0,120, 24,102, 6,126, 30,}, +{ 48, 80, 40, 72, 54, 86, 46, 78,}, +{ 112, 16,104, 8,118, 22,110, 14,}, }; +DECLARE_ALIGNED(8, const uint8_t, ff_sws_pb_64)[8] = +{ 64, 64, 64, 64, 64, 64, 64, 64 }; -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 fillPlane(uint8_t* plane, int stride, + int width, int height, + int y, uint8_t val) +{ + int i; + uint8_t *ptr = plane + stride*y; + for (i=0; isrcFormat].comp[0].depth_minus1; + int sh = bits - 4; for (i = 0; i < dstW; i++) { - int val = 1 << 10; int j; + int srcPos = filterPos[i]; + int val = 0; - 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)); - } + for (j = 0; j < filterSize; j++) { + val += src[srcPos + j] * filter[filterSize * i + j]; } + // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit + dst[i] = FFMIN(val >> sh, (1 << 19) - 1); } } -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) +static void hScale16To15_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *_src, + const int16_t *filter, + const int16_t *filterPos, int filterSize) { - 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..) int i; - for (i=0; i>19); - } + const uint16_t *src = (const uint16_t *) _src; + int sh = av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1; - if (uDest) - for (i=0; i>19); - vDest[i]= av_clip_uint8(v>>19); - } - - if (CONFIG_SWSCALE_ALPHA && aDest) - for (i=0; i>19); + for (j = 0; j < filterSize; j++) { + val += src[srcPos + j] * filter[filterSize * i + j]; } - + // filter=14 bit, input=16 bit, output=30 bit, >> 15 makes 15 bit + dst[i] = FFMIN(val >> sh, (1 << 15) - 1); + } } -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) +// bilinear / bicubic scaling +static void hScale8To15_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, + const int16_t *filter, const int16_t *filterPos, + int filterSize) { - //FIXME Optimize (just quickly written not optimized..) int i; for (i=0; i>19); - } - - if (!uDest) - return; - - if (dstFormat == PIX_FMT_NV12) - for (i=0; i>19); - uDest[2*i+1]= av_clip_uint8(v>>19); - } - else - for (i=0; i>19); - uDest[2*i+1]= av_clip_uint8(u>>19); - } -} - -#define YSCALE_YUV_2_PACKEDX_NOCLIP_C(type,alpha) \ - 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;\ - type av_unused *r, *b, *g;\ - const int i2= 2*i;\ - \ - for (j=0; j>=19;\ - Y2>>=19;\ - U >>=19;\ - V >>=19;\ - if (alpha) {\ - A1 = 1<<18;\ - A2 = 1<<18;\ - for (j=0; j>=19;\ - A2>>=19;\ - } - -#define YSCALE_YUV_2_PACKEDX_C(type,alpha) \ - YSCALE_YUV_2_PACKEDX_NOCLIP_C(type,alpha)\ - 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; \ - }\ - if (alpha && ((A1|A2)&256)) {\ - A1=av_clip_uint8(A1);\ - A2=av_clip_uint8(A2);\ - } - -#define YSCALE_YUV_2_PACKEDX_FULL_C(rnd,alpha) \ - for (i=0; i>=10;\ - U >>=10;\ - V >>=10;\ - if (alpha) {\ - A = rnd;\ - for (j=0; j>=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;\ - Y+= rnd;\ - 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;\ - 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 \ - 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;\ - \ - for (j=0; j>=11;\ - Y2>>=11;\ - 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) \ - 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; \ - if (alpha) {\ - A1= (abuf0[i2 ]*yalpha1+abuf1[i2 ]*yalpha)>>19; \ - A2= (abuf0[i2+1]*yalpha1+abuf1[i2+1]*yalpha)>>19; \ + int srcPos= filterPos[i]; + int val=0; + for (j=0; j>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) \ - 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;\ - int V= (uvbuf1[i+VOFW])>>7;\ - type av_unused *r, *b, *g;\ - int av_unused A1, A2;\ - if (alpha) {\ - A1= abuf0[i2 ]>>7;\ - A2= abuf0[i2+1]>>7;\ - } - -#define YSCALE_YUV_2_GRAY16_1_C \ - 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) \ - 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;\ - 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];\ - for (i=0; i>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;\ - dest++;\ - } - -#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;\ - for (i=0; i>=19;\ - Y2>>=19;\ - 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]];\ - if ((i&7)==6) {\ - ((uint8_t*)dest)[0]= c->dstFormat == PIX_FMT_MONOBLACK ? acc : ~acc;\ - dest++;\ - }\ + //filter += hFilterSize; + dst[i] = FFMIN(val>>7, (1<<15)-1); // the cubic equation does overflow ... + //dst[i] = val>>7; } - -#define YSCALE_YUV_2_ANYRGB_C(func, func2, func_g16, func_monoblack)\ - 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_BGR48BE:\ - case PIX_FMT_BGR48LE:\ - func(uint8_t,0)\ - ((uint8_t*)dest)[ 0] = ((uint8_t*)dest)[ 1] = b[Y1];\ - ((uint8_t*)dest)[ 2] = ((uint8_t*)dest)[ 3] = g[Y1];\ - ((uint8_t*)dest)[ 4] = ((uint8_t*)dest)[ 5] = r[Y1];\ - ((uint8_t*)dest)[ 6] = ((uint8_t*)dest)[ 7] = b[Y2];\ - ((uint8_t*)dest)[ 8] = ((uint8_t*)dest)[ 9] = g[Y2];\ - ((uint8_t*)dest)[10] = ((uint8_t*)dest)[11] = r[Y2];\ - dest+=12;\ - }\ - break;\ - case PIX_FMT_RGBA:\ - case PIX_FMT_BGRA:\ - 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);\ - }\ - } 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);\ - }\ - } 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:\ - 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);\ - }\ - } 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;\ - }\ - } 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_RGB24:\ - 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:\ - case PIX_FMT_MONOWHITE:\ - {\ - 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) -{ - int i; - 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) +static void hScale8To19_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *src, + const int16_t *filter, const int16_t *filterPos, + int filterSize) { int i; - int step= c->dstFormatBpp/8; - int aidx= 3; - - switch(c->dstFormat) { - case PIX_FMT_ARGB: - dest++; - aidx= 0; - case PIX_FMT_RGB24: - aidx--; - case PIX_FMT_RGBA: - 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; - } - } 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; - } - } 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; - } - } - } - break; - case PIX_FMT_ABGR: - dest++; - aidx= 0; - case PIX_FMT_BGR24: - aidx--; - case PIX_FMT_BGRA: - 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; - } - } 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; - } - } 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; - } - } + int32_t *dst = (int32_t *) _dst; + for (i=0; i>3, (1<<19)-1); // the cubic equation does overflow ... + //dst[i] = val>>7; } } -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; - for (i=0; i> RGB2YUV_SHIFT; + dstU[i] = (FFMIN(dstU[i],30775)*4663 - 9289992)>>12; //-264 + dstV[i] = (FFMIN(dstV[i],30775)*4663 - 9289992)>>12; //-264 } } - -static inline void rgb48ToUV(uint8_t *dstU, uint8_t *dstV, - const uint8_t *src1, const uint8_t *src2, - long width, uint32_t *unused) +static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width) { int i; - assert(src1==src2); for (i = 0; i < width; i++) { - int r = src1[6*i + 0]; - int g = src1[6*i + 2]; - int b = src1[6*i + 4]; - - dstU[i] = (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT; - dstV[i] = (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT; + dstU[i] = (dstU[i]*1799 + 4081085)>>11; //1469 + dstV[i] = (dstV[i]*1799 + 4081085)>>11; //1469 } } - -static inline void rgb48ToUV_half(uint8_t *dstU, uint8_t *dstV, - const uint8_t *src1, const uint8_t *src2, - long width, uint32_t *unused) +static void lumRangeToJpeg_c(int16_t *dst, int width) { int i; - assert(src1==src2); - for (i = 0; i < width; i++) { - int r= src1[12*i + 0] + src1[12*i + 6]; - int g= src1[12*i + 2] + src1[12*i + 8]; - int b= src1[12*i + 4] + src1[12*i + 10]; - - dstU[i]= (RU*r + GU*g + BU*b + (257<> (RGB2YUV_SHIFT+1); - dstV[i]= (RV*r + GV*g + BV*b + (257<> (RGB2YUV_SHIFT+1); - } + for (i = 0; i < width; i++) + dst[i] = (FFMIN(dst[i],30189)*19077 - 39057361)>>14; } - -static inline void bgr48ToY(uint8_t *dst, const uint8_t *src, long width, - uint32_t *unused) +static void lumRangeFromJpeg_c(int16_t *dst, int width) { int i; - for (i = 0; i < width; i++) { - int b = src[i*6+0]; - int g = src[i*6+2]; - int r = src[i*6+4]; - - dst[i] = (RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT; - } + for (i = 0; i < width; i++) + dst[i] = (dst[i]*14071 + 33561947)>>14; } -static inline void bgr48ToUV(uint8_t *dstU, uint8_t *dstV, - const uint8_t *src1, const uint8_t *src2, - long width, uint32_t *unused) +static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width) { int i; + int32_t *dstU = (int32_t *) _dstU; + int32_t *dstV = (int32_t *) _dstV; for (i = 0; i < width; i++) { - int b = src1[6*i + 0]; - int g = src1[6*i + 2]; - int r = src1[6*i + 4]; - - dstU[i] = (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT; - dstV[i] = (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT; + dstU[i] = (FFMIN(dstU[i],30775<<4)*4663 - (9289992<<4))>>12; //-264 + dstV[i] = (FFMIN(dstV[i],30775<<4)*4663 - (9289992<<4))>>12; //-264 } } - -static inline void bgr48ToUV_half(uint8_t *dstU, uint8_t *dstV, - const uint8_t *src1, const uint8_t *src2, - long width, uint32_t *unused) +static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width) { int i; + int32_t *dstU = (int32_t *) _dstU; + int32_t *dstV = (int32_t *) _dstV; for (i = 0; i < width; i++) { - int b= src1[12*i + 0] + src1[12*i + 6]; - int g= src1[12*i + 2] + src1[12*i + 8]; - int r= src1[12*i + 4] + src1[12*i + 10]; - - dstU[i]= (RU*r + GU*g + BU*b + (257<> (RGB2YUV_SHIFT+1); - dstV[i]= (RV*r + GV*g + BV*b + (257<> (RGB2YUV_SHIFT+1); + dstU[i] = (dstU[i]*1799 + (4081085<<4))>>11; //1469 + dstV[i] = (dstV[i]*1799 + (4081085<<4))>>11; //1469 } } - -#define BGR2Y(type, name, shr, shg, shb, maskr, maskg, maskb, RY, GY, BY, S)\ -static inline void name(uint8_t *dst, const uint8_t *src, long width, uint32_t *unused)\ -{\ - int i;\ - for (i=0; i>shb)&maskb;\ - int g= (((const type*)src)[i]>>shg)&maskg;\ - int r= (((const type*)src)[i]>>shr)&maskr;\ -\ - dst[i]= (((RY)*r + (GY)*g + (BY)*b + (33<<((S)-1)))>>(S));\ - }\ -} - -BGR2Y(uint32_t, bgr32ToY,16, 0, 0, 0x00FF, 0xFF00, 0x00FF, RY<< 8, GY , BY<< 8, RGB2YUV_SHIFT+8) -BGR2Y(uint32_t,bgr321ToY,16,16, 0, 0xFF00, 0x00FF, 0xFF00, RY , GY<<8, BY , RGB2YUV_SHIFT+8) -BGR2Y(uint32_t, rgb32ToY, 0, 0,16, 0x00FF, 0xFF00, 0x00FF, RY<< 8, GY , BY<< 8, RGB2YUV_SHIFT+8) -BGR2Y(uint32_t,rgb321ToY, 0,16,16, 0xFF00, 0x00FF, 0xFF00, RY , GY<<8, BY , RGB2YUV_SHIFT+8) -BGR2Y(uint16_t, bgr16ToY, 0, 0, 0, 0x001F, 0x07E0, 0xF800, RY<<11, GY<<5, BY , RGB2YUV_SHIFT+8) -BGR2Y(uint16_t, bgr15ToY, 0, 0, 0, 0x001F, 0x03E0, 0x7C00, RY<<10, GY<<5, BY , RGB2YUV_SHIFT+7) -BGR2Y(uint16_t, rgb16ToY, 0, 0, 0, 0xF800, 0x07E0, 0x001F, RY , GY<<5, BY<<11, RGB2YUV_SHIFT+8) -BGR2Y(uint16_t, rgb15ToY, 0, 0, 0, 0x7C00, 0x03E0, 0x001F, RY , GY<<5, BY<<10, RGB2YUV_SHIFT+7) - -static inline void abgrToA(uint8_t *dst, const uint8_t *src, long width, uint32_t *unused) +static void lumRangeToJpeg16_c(int16_t *_dst, int width) { int i; - for (i=0; i>shp)&maskb)>>shb;\ - int g= ((((const type*)src)[i]>>shp)&maskg)>>shg;\ - int r= ((((const type*)src)[i]>>shp)&maskr)>>shr;\ -\ - dstU[i]= ((RU)*r + (GU)*g + (BU)*b + (257<<((S)-1)))>>(S);\ - dstV[i]= ((RV)*r + (GV)*g + (BV)*b + (257<<((S)-1)))>>(S);\ - }\ -}\ -static inline void name ## _half(uint8_t *dstU, uint8_t *dstV, const uint8_t *src, const uint8_t *dummy, long width, uint32_t *unused)\ -{\ - int i;\ - for (i=0; i>shp;\ - int pix1= ((const type*)src)[2*i+1]>>shp;\ - int g= (pix0&~(maskr|maskb))+(pix1&~(maskr|maskb));\ - int b= ((pix0+pix1-g)&(maskb|(2*maskb)))>>shb;\ - int r= ((pix0+pix1-g)&(maskr|(2*maskr)))>>shr;\ - g&= maskg|(2*maskg);\ -\ - g>>=shg;\ -\ - dstU[i]= ((RU)*r + (GU)*g + (BU)*b + (257<<(S)))>>((S)+1);\ - dstV[i]= ((RV)*r + (GV)*g + (BV)*b + (257<<(S)))>>((S)+1);\ - }\ + int32_t *dst = (int32_t *) _dst; + for (i = 0; i < width; i++) + dst[i] = (FFMIN(dst[i],30189<<4)*4769 - (39057361<<2))>>12; } - -BGR2UV(uint32_t, bgr32ToUV,16, 0, 0, 0, 0xFF0000, 0xFF00, 0x00FF, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8) -BGR2UV(uint32_t,bgr321ToUV,16, 0, 0, 8, 0xFF0000, 0xFF00, 0x00FF, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8) -BGR2UV(uint32_t, rgb32ToUV, 0, 0,16, 0, 0x00FF, 0xFF00, 0xFF0000, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8) -BGR2UV(uint32_t,rgb321ToUV, 0, 0,16, 8, 0x00FF, 0xFF00, 0xFF0000, RU<< 8, GU , BU<< 8, RV<< 8, GV , BV<< 8, RGB2YUV_SHIFT+8) -BGR2UV(uint16_t, bgr16ToUV, 0, 0, 0, 0, 0x001F, 0x07E0, 0xF800, RU<<11, GU<<5, BU , RV<<11, GV<<5, BV , RGB2YUV_SHIFT+8) -BGR2UV(uint16_t, bgr15ToUV, 0, 0, 0, 0, 0x001F, 0x03E0, 0x7C00, RU<<10, GU<<5, BU , RV<<10, GV<<5, BV , RGB2YUV_SHIFT+7) -BGR2UV(uint16_t, rgb16ToUV, 0, 0, 0, 0, 0xF800, 0x07E0, 0x001F, RU , GU<<5, BU<<11, RV , GV<<5, BV<<11, RGB2YUV_SHIFT+8) -BGR2UV(uint16_t, rgb15ToUV, 0, 0, 0, 0, 0x7C00, 0x03E0, 0x001F, RU , GU<<5, BU<<10, RV , GV<<5, BV<<10, RGB2YUV_SHIFT+7) - -static inline void palToY(uint8_t *dst, const uint8_t *src, long width, uint32_t *pal) +static void lumRangeFromJpeg16_c(int16_t *_dst, int width) { int i; - for (i=0; i>14; } -static inline void palToUV(uint8_t *dstU, uint8_t *dstV, - const uint8_t *src1, const uint8_t *src2, - long width, uint32_t *pal) +static void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth, + const uint8_t *src, int srcW, int xInc) { int i; - assert(src1 == src2); - for (i=0; i>8; - dstV[i]= p>>16; - } -} - -static inline void monowhite2Y(uint8_t *dst, const uint8_t *src, long width, uint32_t *unused) -{ - int i, j; - for (i=0; i>(7-j))&1)*255; - } -} - -static inline void monoblack2Y(uint8_t *dst, const uint8_t *src, long width, uint32_t *unused) -{ - int i, j; - for (i=0; i>(7-j))&1)*255; + unsigned int xpos=0; + for (i=0;i>16; + register unsigned int xalpha=(xpos&0xFFFF)>>9; + dst[i]= (src[xx]<<7) + (src[xx+1] - src[xx])*xalpha; + xpos+=xInc; } } -//Note: we have C, MMX, MMX2, 3DNOW versions, there is no 3DNOW+MMX2 one -//Plain C versions -#if CONFIG_RUNTIME_CPUDETECT -# define COMPILE_C 1 -# if ARCH_X86 -# define COMPILE_MMX HAVE_MMX -# define COMPILE_MMX2 HAVE_MMX2 -# define COMPILE_3DNOW HAVE_AMD3DNOW -# elif ARCH_PPC -# define COMPILE_ALTIVEC HAVE_ALTIVEC -# endif -#else /* CONFIG_RUNTIME_CPUDETECT */ -# if ARCH_X86 -# if HAVE_MMX2 -# define COMPILE_MMX2 1 -# elif HAVE_AMD3DNOW -# define COMPILE_3DNOW 1 -# elif HAVE_MMX -# define COMPILE_MMX 1 -# else -# define COMPILE_C 1 -# endif -# elif ARCH_PPC && HAVE_ALTIVEC -# define COMPILE_ALTIVEC 1 -# else -# define COMPILE_C 1 -# endif -#endif - -#ifndef COMPILE_C -# define COMPILE_C 0 -#endif -#ifndef COMPILE_MMX -# define COMPILE_MMX 0 -#endif -#ifndef COMPILE_MMX2 -# define COMPILE_MMX2 0 -#endif -#ifndef COMPILE_3DNOW -# define COMPILE_3DNOW 0 -#endif -#ifndef COMPILE_ALTIVEC -# define COMPILE_ALTIVEC 0 -#endif - -#define COMPILE_TEMPLATE_MMX 0 -#define COMPILE_TEMPLATE_MMX2 0 -#define COMPILE_TEMPLATE_AMD3DNOW 0 -#define COMPILE_TEMPLATE_ALTIVEC 0 - -#include "swscale_template.c" - -#if COMPILE_ALTIVEC -#undef RENAME -#undef COMPILE_TEMPLATE_ALTIVEC -#define COMPILE_TEMPLATE_ALTIVEC 1 -#define RENAME(a) a ## _altivec -#include "ppc/swscale_template.c" -#endif - -#if ARCH_X86 - -//MMX versions -#if COMPILE_MMX -#undef RENAME -#undef COMPILE_TEMPLATE_MMX -#undef COMPILE_TEMPLATE_MMX2 -#undef COMPILE_TEMPLATE_AMD3DNOW -#define COMPILE_TEMPLATE_MMX 1 -#define COMPILE_TEMPLATE_MMX2 0 -#define COMPILE_TEMPLATE_AMD3DNOW 0 -#define RENAME(a) a ## _MMX -#include "x86/swscale_template.c" -#endif - -//MMX2 versions -#if COMPILE_MMX2 -#undef RENAME -#undef COMPILE_TEMPLATE_MMX -#undef COMPILE_TEMPLATE_MMX2 -#undef COMPILE_TEMPLATE_AMD3DNOW -#define COMPILE_TEMPLATE_MMX 1 -#define COMPILE_TEMPLATE_MMX2 1 -#define COMPILE_TEMPLATE_AMD3DNOW 0 -#define RENAME(a) a ## _MMX2 -#include "x86/swscale_template.c" -#endif - -//3DNOW versions -#if COMPILE_3DNOW -#undef RENAME -#undef COMPILE_TEMPLATE_MMX -#undef COMPILE_TEMPLATE_MMX2 -#undef COMPILE_TEMPLATE_AMD3DNOW -#define COMPILE_TEMPLATE_MMX 1 -#define COMPILE_TEMPLATE_MMX2 0 -#define COMPILE_TEMPLATE_AMD3DNOW 1 -#define RENAME(a) a ## _3DNow -#include "x86/swscale_template.c" -#endif - -#endif //ARCH_X86 - -SwsFunc ff_getSwsFunc(SwsContext *c) +// *** horizontal scale Y line to temp buffer +static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth, + const uint8_t *src_in[4], int srcW, int xInc, + const int16_t *hLumFilter, + const int16_t *hLumFilterPos, int hLumFilterSize, + uint8_t *formatConvBuffer, + uint32_t *pal, int isAlpha) { - sws_init_swScale_c(c); - -#if CONFIG_RUNTIME_CPUDETECT -#if ARCH_X86 - // ordered per speed fastest first - if (c->flags & SWS_CPU_CAPS_MMX2) { - sws_init_swScale_MMX2(c); - return swScale_MMX2; - } else if (c->flags & SWS_CPU_CAPS_3DNOW) { - sws_init_swScale_3DNow(c); - return swScale_3DNow; - } else if (c->flags & SWS_CPU_CAPS_MMX) { - sws_init_swScale_MMX(c); - return swScale_MMX; - } + void (*toYV12)(uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12; + void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange; + const uint8_t *src = src_in[isAlpha ? 3 : 0]; -#else -#if COMPILE_ALTIVEC - if (c->flags & SWS_CPU_CAPS_ALTIVEC) { - sws_init_swScale_altivec(c); - return swScale_altivec; + if (toYV12) { + toYV12(formatConvBuffer, src, srcW, pal); + src= formatConvBuffer; + } else if (c->readLumPlanar && !isAlpha) { + c->readLumPlanar(formatConvBuffer, src_in, srcW); + src = formatConvBuffer; } -#endif -#endif /* ARCH_X86 */ -#else //CONFIG_RUNTIME_CPUDETECT -#if COMPILE_TEMPLATE_MMX2 - sws_init_swScale_MMX2(c); - return swScale_MMX2; -#elif COMPILE_TEMPLATE_AMD3DNOW - sws_init_swScale_3DNow(c); - return swScale_3DNow; -#elif COMPILE_TEMPLATE_MMX - sws_init_swScale_MMX(c); - return swScale_MMX; -#elif COMPILE_TEMPLATE_ALTIVEC - sws_init_swScale_altivec(c); - return swScale_altivec; -#endif -#endif //!CONFIG_RUNTIME_CPUDETECT - return swScale_c; -} - -static void copyPlane(const uint8_t *src, int srcStride, - int srcSliceY, int srcSliceH, int width, - uint8_t *dst, int dstStride) -{ - dst += dstStride * srcSliceY; - if (dstStride == srcStride && srcStride > 0) { - memcpy(dst, src, srcSliceH * dstStride); - } else { - int i; - for (i=0; ihyscale_fast) { + c->hyScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize); + } else { // fast bilinear upscale / crap downscale + c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc); } -} - -static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) -{ - uint8_t *dst = dstParam[1] + dstStride[1]*srcSliceY/2; - - copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, - dstParam[0], dstStride[0]); - - if (c->dstFormat == PIX_FMT_NV12) - interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]); - else - interleaveBytes(src[2], src[1], dst, c->srcW/2, srcSliceH/2, srcStride[2], srcStride[1], dstStride[0]); - - return srcSliceH; -} - -static int planarToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) -{ - uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; - - yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]); - return srcSliceH; + if (convertRange) + convertRange(dst, dstWidth); } -static int planarToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) +static void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2, + int dstWidth, const uint8_t *src1, + const uint8_t *src2, int srcW, int xInc) { - uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; - - yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]); - - return srcSliceH; -} - -static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) -{ - uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; - - yuv422ptoyuy2(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]); - - return srcSliceH; -} - -static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) -{ - uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; - - yuv422ptouyvy(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]); - - return srcSliceH; -} - -static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) -{ - uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY; - uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2; - uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2; - - yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); - - if (dstParam[3]) - fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); - - return srcSliceH; -} - -static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) -{ - uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY; - uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY; - uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY; - - yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); - - return srcSliceH; -} - -static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) -{ - uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY; - uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2; - uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2; - - uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); - - if (dstParam[3]) - fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); - - return srcSliceH; -} - -static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dstParam[], int dstStride[]) -{ - uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY; - uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY; - uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY; - - uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); - - return srcSliceH; -} - -static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette) -{ - long i; - for (i=0; isrcFormat; - const enum PixelFormat dstFormat= c->dstFormat; - void (*conv)(const uint8_t *src, uint8_t *dst, long num_pixels, - const uint8_t *palette)=NULL; int i; - uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY; - const uint8_t *srcPtr= src[0]; - - if (srcFormat == PIX_FMT_Y400A) { - switch (dstFormat) { - case PIX_FMT_RGB32 : conv = gray8aToPacked32; break; - case PIX_FMT_BGR32 : conv = gray8aToPacked32; break; - case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break; - case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break; - case PIX_FMT_RGB24 : conv = gray8aToPacked24; break; - case PIX_FMT_BGR24 : conv = gray8aToPacked24; break; - } - } else if (usePal(srcFormat)) { - switch (dstFormat) { - case PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break; - case PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break; - case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break; - case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break; - case PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break; - case PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break; + unsigned int xpos=0; + for (i=0;i>16; + register unsigned int xalpha=(xpos&0xFFFF)>>9; + dst1[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha); + dst2[i]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha); + xpos+=xInc; + } +} + +static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2, int dstWidth, + const uint8_t *src_in[4], + int srcW, int xInc, const int16_t *hChrFilter, + const int16_t *hChrFilterPos, int hChrFilterSize, + uint8_t *formatConvBuffer, uint32_t *pal) +{ + const uint8_t *src1 = src_in[1], *src2 = src_in[2]; + if (c->chrToYV12) { + uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW * FFALIGN(c->srcBpc, 8) >> 3, 16); + c->chrToYV12(formatConvBuffer, buf2, src1, src2, srcW, pal); + src1= formatConvBuffer; + src2= buf2; + } else if (c->readChrPlanar) { + uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW * FFALIGN(c->srcBpc, 8) >> 3, 16); + c->readChrPlanar(formatConvBuffer, buf2, src_in, srcW); + src1= formatConvBuffer; + src2= buf2; + } + + if (!c->hcscale_fast) { + c->hcScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize); + c->hcScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize); + } else { // fast bilinear upscale / crap downscale + c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc); + } + + if (c->chrConvertRange) + c->chrConvertRange(dst1, dst2, dstWidth); +} + +#define DEBUG_SWSCALE_BUFFERS 0 +#define DEBUG_BUFFERS(...) if (DEBUG_SWSCALE_BUFFERS) av_log(c, AV_LOG_DEBUG, __VA_ARGS__) + +static int swScale(SwsContext *c, const uint8_t* src[], + int srcStride[], int srcSliceY, + int srcSliceH, uint8_t* dst[], int dstStride[]) +{ + /* load a few things into local vars to make the code more readable? and faster */ + const int srcW= c->srcW; + const int dstW= c->dstW; + const int dstH= c->dstH; + const int chrDstW= c->chrDstW; + const int chrSrcW= c->chrSrcW; + const int lumXInc= c->lumXInc; + const int chrXInc= c->chrXInc; + const enum PixelFormat dstFormat= c->dstFormat; + const int flags= c->flags; + int16_t *vLumFilterPos= c->vLumFilterPos; + int16_t *vChrFilterPos= c->vChrFilterPos; + int16_t *hLumFilterPos= c->hLumFilterPos; + int16_t *hChrFilterPos= c->hChrFilterPos; + int16_t *vLumFilter= c->vLumFilter; + int16_t *vChrFilter= c->vChrFilter; + int16_t *hLumFilter= c->hLumFilter; + int16_t *hChrFilter= c->hChrFilter; + int32_t *lumMmxFilter= c->lumMmxFilter; + int32_t *chrMmxFilter= c->chrMmxFilter; + const int vLumFilterSize= c->vLumFilterSize; + const int vChrFilterSize= c->vChrFilterSize; + const int hLumFilterSize= c->hLumFilterSize; + const int hChrFilterSize= c->hChrFilterSize; + int16_t **lumPixBuf= c->lumPixBuf; + int16_t **chrUPixBuf= c->chrUPixBuf; + int16_t **chrVPixBuf= c->chrVPixBuf; + int16_t **alpPixBuf= c->alpPixBuf; + const int vLumBufSize= c->vLumBufSize; + const int vChrBufSize= c->vChrBufSize; + uint8_t *formatConvBuffer= c->formatConvBuffer; + const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample; + const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample); + int lastDstY; + uint32_t *pal=c->pal_yuv; + yuv2planar1_fn yuv2plane1 = c->yuv2plane1; + yuv2planarX_fn yuv2planeX = c->yuv2planeX; + yuv2interleavedX_fn yuv2nv12cX = c->yuv2nv12cX; + yuv2packed1_fn yuv2packed1 = c->yuv2packed1; + yuv2packed2_fn yuv2packed2 = c->yuv2packed2; + yuv2packedX_fn yuv2packedX = c->yuv2packedX; + int should_dither = is9_OR_10BPS(c->srcFormat) || is16BPS(c->srcFormat); + + /* vars which will change and which we need to store back in the context */ + int dstY= c->dstY; + int lumBufIndex= c->lumBufIndex; + int chrBufIndex= c->chrBufIndex; + int lastInLumBuf= c->lastInLumBuf; + int lastInChrBuf= c->lastInChrBuf; + + if (isPacked(c->srcFormat)) { + src[0]= + src[1]= + src[2]= + src[3]= src[0]; + srcStride[0]= + srcStride[1]= + srcStride[2]= + srcStride[3]= srcStride[0]; + } + srcStride[1]<<= c->vChrDrop; + srcStride[2]<<= c->vChrDrop; + + DEBUG_BUFFERS("swScale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n", + src[0], srcStride[0], src[1], srcStride[1], src[2], srcStride[2], src[3], srcStride[3], + dst[0], dstStride[0], dst[1], dstStride[1], dst[2], dstStride[2], dst[3], dstStride[3]); + DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n", + srcSliceY, srcSliceH, dstY, dstH); + DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n", + vLumFilterSize, vLumBufSize, vChrFilterSize, vChrBufSize); + + if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) { + static int warnedAlready=0; //FIXME move this into the context perhaps + if (flags & SWS_PRINT_INFO && !warnedAlready) { + av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n" + " ->cannot do aligned memory accesses anymore\n"); + warnedAlready=1; } } - if (!conv) - av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", - sws_format_name(srcFormat), sws_format_name(dstFormat)); - else { - for (i=0; isrcW, (uint8_t *) c->pal_rgb); - srcPtr+= srcStride[0]; - dstPtr+= dstStride[0]; + /* Note the user might start scaling the picture in the middle so this + will not get executed. This is not really intended but works + currently, so people might do it. */ + if (srcSliceY ==0) { + lumBufIndex=-1; + chrBufIndex=-1; + dstY=0; + lastInLumBuf= -1; + lastInChrBuf= -1; + } + + if (!should_dither) { + c->chrDither8 = c->lumDither8 = ff_sws_pb_64; + } + lastDstY= dstY; + + for (;dstY < dstH; dstY++) { + const int chrDstY= dstY>>c->chrDstVSubSample; + uint8_t *dest[4] = { + dst[0] + dstStride[0] * dstY, + dst[1] + dstStride[1] * chrDstY, + dst[2] + dstStride[2] * chrDstY, + (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3] + dstStride[3] * dstY : NULL, + }; + + const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input + const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<chrDstVSubSample) - 1), dstH-1)]; + const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input + + // Last line needed as input + int lastLumSrcY = FFMIN(c->srcH, firstLumSrcY + vLumFilterSize) - 1; + int lastLumSrcY2 = FFMIN(c->srcH, firstLumSrcY2 + vLumFilterSize) - 1; + int lastChrSrcY = FFMIN(c->chrSrcH, firstChrSrcY + vChrFilterSize) - 1; + int enough_lines; + + //handle holes (FAST_BILINEAR & weird filters) + if (firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1; + if (firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1; + assert(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1); + assert(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1); + + DEBUG_BUFFERS("dstY: %d\n", dstY); + DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n", + firstLumSrcY, lastLumSrcY, lastInLumBuf); + DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n", + firstChrSrcY, lastChrSrcY, lastInChrBuf); + + // Do we have enough lines in this slice to output the dstY line + enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample); + + if (!enough_lines) { + lastLumSrcY = srcSliceY + srcSliceH - 1; + lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1; + DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n", + lastLumSrcY, lastChrSrcY); } - } - - return srcSliceH; -} - -#define isRGBA32(x) ( \ - (x) == PIX_FMT_ARGB \ - || (x) == PIX_FMT_RGBA \ - || (x) == PIX_FMT_BGRA \ - || (x) == PIX_FMT_ABGR \ - ) -/* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ -static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dst[], int dstStride[]) -{ - const enum PixelFormat srcFormat= c->srcFormat; - const enum PixelFormat dstFormat= c->dstFormat; - const int srcBpp= (c->srcFormatBpp + 7) >> 3; - const int dstBpp= (c->dstFormatBpp + 7) >> 3; - const int srcId= c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */ - const int dstId= c->dstFormatBpp >> 2; - void (*conv)(const uint8_t *src, uint8_t *dst, long src_size)=NULL; - -#define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst) - - if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) { - if ( CONV_IS(ABGR, RGBA) - || CONV_IS(ARGB, BGRA) - || CONV_IS(BGRA, ARGB) - || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210; - else if (CONV_IS(ABGR, ARGB) - || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321; - else if (CONV_IS(ABGR, BGRA) - || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230; - else if (CONV_IS(BGRA, RGBA) - || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103; - else if (CONV_IS(BGRA, ABGR) - || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012; - } else - /* BGR -> BGR */ - if ( (isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) - || (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) { - switch(srcId | (dstId<<4)) { - case 0x34: conv= rgb16to15; break; - case 0x36: conv= rgb24to15; break; - case 0x38: conv= rgb32to15; break; - case 0x43: conv= rgb15to16; break; - case 0x46: conv= rgb24to16; break; - case 0x48: conv= rgb32to16; break; - case 0x63: conv= rgb15to24; break; - case 0x64: conv= rgb16to24; break; - case 0x68: conv= rgb32to24; break; - case 0x83: conv= rgb15to32; break; - case 0x84: conv= rgb16to32; break; - case 0x86: conv= rgb24to32; break; + //Do horizontal scaling + while(lastInLumBuf < lastLumSrcY) { + const uint8_t *src1[4] = { + src[0] + (lastInLumBuf + 1 - srcSliceY) * srcStride[0], + src[1] + (lastInLumBuf + 1 - srcSliceY) * srcStride[1], + src[2] + (lastInLumBuf + 1 - srcSliceY) * srcStride[2], + src[3] + (lastInLumBuf + 1 - srcSliceY) * srcStride[3], + }; + lumBufIndex++; + assert(lumBufIndex < 2*vLumBufSize); + assert(lastInLumBuf + 1 - srcSliceY < srcSliceH); + assert(lastInLumBuf + 1 - srcSliceY >= 0); + hyscale(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc, + hLumFilter, hLumFilterPos, hLumFilterSize, + formatConvBuffer, + pal, 0); + if (CONFIG_SWSCALE_ALPHA && alpPixBuf) + hyscale(c, alpPixBuf[ lumBufIndex ], dstW, src1, srcW, + lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize, + formatConvBuffer, + pal, 1); + lastInLumBuf++; + DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n", + lumBufIndex, lastInLumBuf); } - } else if ( (isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) - || (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) { - switch(srcId | (dstId<<4)) { - case 0x33: conv= rgb15tobgr15; break; - case 0x34: conv= rgb16tobgr15; break; - case 0x36: conv= rgb24tobgr15; break; - case 0x38: conv= rgb32tobgr15; break; - case 0x43: conv= rgb15tobgr16; break; - case 0x44: conv= rgb16tobgr16; break; - case 0x46: conv= rgb24tobgr16; break; - case 0x48: conv= rgb32tobgr16; break; - case 0x63: conv= rgb15tobgr24; break; - case 0x64: conv= rgb16tobgr24; break; - case 0x66: conv= rgb24tobgr24; break; - case 0x68: conv= rgb32tobgr24; break; - case 0x83: conv= rgb15tobgr32; break; - case 0x84: conv= rgb16tobgr32; break; - case 0x86: conv= rgb24tobgr32; break; + while(lastInChrBuf < lastChrSrcY) { + const uint8_t *src1[4] = { + src[0] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[0], + src[1] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[1], + src[2] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[2], + src[3] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[3], + }; + chrBufIndex++; + assert(chrBufIndex < 2*vChrBufSize); + assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH)); + assert(lastInChrBuf + 1 - chrSrcSliceY >= 0); + //FIXME replace parameters through context struct (some at least) + + if (c->needs_hcscale) + hcscale(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex], + chrDstW, src1, chrSrcW, chrXInc, + hChrFilter, hChrFilterPos, hChrFilterSize, + formatConvBuffer, pal); + lastInChrBuf++; + DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n", + chrBufIndex, lastInChrBuf); } - } - - if (!conv) { - av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", - sws_format_name(srcFormat), sws_format_name(dstFormat)); - } else { - const uint8_t *srcPtr= src[0]; - uint8_t *dstPtr= dst[0]; - if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && !isRGBA32(dstFormat)) - srcPtr += ALT32_CORR; - - if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat)) - dstPtr += ALT32_CORR; - - if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0) - conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]); - else { - int i; - dstPtr += dstStride[0]*srcSliceY; - - for (i=0; isrcW*srcBpp); - srcPtr+= srcStride[0]; - dstPtr+= dstStride[0]; - } + //wrap buf index around to stay inside the ring buffer + if (lumBufIndex >= vLumBufSize) lumBufIndex-= vLumBufSize; + if (chrBufIndex >= vChrBufSize) chrBufIndex-= vChrBufSize; + if (!enough_lines) + break; //we can't output a dstY line so let's try with the next slice + +#if HAVE_MMX + updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, lastInLumBuf, lastInChrBuf); +#endif + if (should_dither) { + c->chrDither8 = dither_8x8_128[chrDstY & 7]; + c->lumDither8 = dither_8x8_128[dstY & 7]; } - } - return srcSliceH; -} - -static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dst[], int dstStride[]) -{ - rgb24toyv12( - src[0], - dst[0]+ srcSliceY *dstStride[0], - dst[1]+(srcSliceY>>1)*dstStride[1], - dst[2]+(srcSliceY>>1)*dstStride[2], - c->srcW, srcSliceH, - dstStride[0], dstStride[1], srcStride[0]); - if (dst[3]) - fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); - return srcSliceH; -} - -static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dst[], int dstStride[]) -{ - copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, - dst[0], dstStride[0]); - - planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW, - srcSliceH >> 2, srcStride[1], dstStride[1]); - planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW, - srcSliceH >> 2, srcStride[2], dstStride[2]); - if (dst[3]) - fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); - return srcSliceH; -} - -/* unscaled copy like stuff (assumes nearly identical formats) */ -static int packedCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dst[], int dstStride[]) -{ - if (dstStride[0]==srcStride[0] && srcStride[0] > 0) - memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]); - else { - int i; - const uint8_t *srcPtr= src[0]; - uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY; - int length=0; - - /* universal length finder */ - while(length+c->srcW <= FFABS(dstStride[0]) - && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW; - assert(length!=0); - - for (i=0; i= dstH-2) { + // hmm looks like we can't use MMX here without overwriting this array's tail + ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX, + &yuv2packed1, &yuv2packed2, &yuv2packedX); } - } - return srcSliceH; -} -static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* dst[], int dstStride[]) -{ - int plane, i, j; - for (plane=0; plane<4; plane++) { - int length= (plane==0 || plane==3) ? c->srcW : -((-c->srcW )>>c->chrDstHSubSample); - int y= (plane==0 || plane==3) ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample); - int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample); - const uint8_t *srcPtr= src[plane]; - uint8_t *dstPtr= dst[plane] + dstStride[plane]*y; + { + const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize; + const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize; + const int16_t **chrVSrcPtr= (const int16_t **) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize; + const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL; + + if (firstLumSrcY < 0 || firstLumSrcY + vLumFilterSize > c->srcH) { + const int16_t **tmpY = (const int16_t **) lumPixBuf + 2 * vLumBufSize; + int neg = -firstLumSrcY, i, end = FFMIN(c->srcH - firstLumSrcY, vLumFilterSize); + for (i = 0; i < neg; i++) + tmpY[i] = lumSrcPtr[neg]; + for ( ; i < end; i++) + tmpY[i] = lumSrcPtr[i]; + for ( ; i < vLumFilterSize; i++) + tmpY[i] = tmpY[i-1]; + lumSrcPtr = tmpY; + + if (alpSrcPtr) { + const int16_t **tmpA = (const int16_t **) alpPixBuf + 2 * vLumBufSize; + for (i = 0; i < neg; i++) + tmpA[i] = alpSrcPtr[neg]; + for ( ; i < end; i++) + tmpA[i] = alpSrcPtr[i]; + for ( ; i < vLumFilterSize; i++) + tmpA[i] = tmpA[i - 1]; + alpSrcPtr = tmpA; + } + } + if (firstChrSrcY < 0 || firstChrSrcY + vChrFilterSize > c->chrSrcH) { + const int16_t **tmpU = (const int16_t **) chrUPixBuf + 2 * vChrBufSize, + **tmpV = (const int16_t **) chrVPixBuf + 2 * vChrBufSize; + int neg = -firstChrSrcY, i, end = FFMIN(c->chrSrcH - firstChrSrcY, vChrFilterSize); + for (i = 0; i < neg; i++) { + tmpU[i] = chrUSrcPtr[neg]; + tmpV[i] = chrVSrcPtr[neg]; + } + for ( ; i < end; i++) { + tmpU[i] = chrUSrcPtr[i]; + tmpV[i] = chrVSrcPtr[i]; + } + for ( ; i < vChrFilterSize; i++) { + tmpU[i] = tmpU[i - 1]; + tmpV[i] = tmpV[i - 1]; + } + chrUSrcPtr = tmpU; + chrVSrcPtr = tmpV; + } - if (!dst[plane]) continue; - // ignore palette for GRAY8 - if (plane == 1 && !dst[2]) continue; - if (!src[plane] || (plane == 1 && !src[2])) { - if(is16BPS(c->dstFormat)) - length*=2; - fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128); - } else { - if(isNBPS(c->srcFormat)) { - const int depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1; - uint16_t *srcPtr2 = (uint16_t*)srcPtr; + if (isPlanarYUV(dstFormat) || (isGray(dstFormat) && !isALPHA(dstFormat))) { //YV12 like + const int chrSkipMask= (1<chrDstVSubSample)-1; - if (is16BPS(c->dstFormat)) { - uint16_t *dstPtr2 = (uint16_t*)dstPtr; - for (i = 0; i < height; i++) { - for (j = 0; j < length; j++) - dstPtr2[j] = (srcPtr2[j]<<(16-depth)) | (srcPtr2[j]>>(2*depth-16)); - dstPtr2 += dstStride[plane]/2; - srcPtr2 += srcStride[plane]/2; - } + if (vLumFilterSize == 1) { + yuv2plane1(lumSrcPtr[0], dest[0], dstW, c->lumDither8, 0); } else { - // FIXME Maybe dither instead. - for (i = 0; i < height; i++) { - for (j = 0; j < length; j++) - dstPtr[j] = srcPtr2[j]>>(depth-8); - dstPtr += dstStride[plane]; - srcPtr2 += srcStride[plane]/2; - } - } - } else if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) { - if (!isBE(c->srcFormat)) srcPtr++; - for (i=0; ilumDither8, 0); } - } else if(!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) { - for (i=0; ichrDither8, 0); + yuv2plane1(chrVSrcPtr[0], dest[2], chrDstW, c->chrDither8, 3); + } else { + yuv2planeX(vChrFilter + chrDstY * vChrFilterSize, vChrFilterSize, + chrUSrcPtr, dest[1], chrDstW, c->chrDither8, 0); + yuv2planeX(vChrFilter + chrDstY * vChrFilterSize, vChrFilterSize, + chrVSrcPtr, dest[2], chrDstW, c->chrDither8, 3); } - srcPtr+= srcStride[plane]; - dstPtr+= dstStride[plane]; } - } else if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat) - && isBE(c->srcFormat) != isBE(c->dstFormat)) { - for (i=0; ilumDither8, 0); + } else { + yuv2planeX(vLumFilter + dstY * vLumFilterSize, vLumFilterSize, + alpSrcPtr, dest[3], dstW, c->lumDither8, 0); + } } - } else if (dstStride[plane] == srcStride[plane] && - srcStride[plane] > 0 && srcStride[plane] == length) { - memcpy(dst[plane] + dstStride[plane]*y, src[plane], - height*dstStride[plane]); } else { - if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) - length*=2; - for (i=0; iyuv2packed1 && vLumFilterSize == 1 && vChrFilterSize <= 2) { //unscaled RGB + int chrAlpha = vChrFilterSize == 1 ? 0 : vChrFilter[2 * dstY + 1]; + yuv2packed1(c, *lumSrcPtr, chrUSrcPtr, chrVSrcPtr, + alpPixBuf ? *alpSrcPtr : NULL, + dest[0], dstW, chrAlpha, dstY); + } else if (c->yuv2packed2 && vLumFilterSize == 2 && vChrFilterSize == 2) { //bilinear upscale RGB + int lumAlpha = vLumFilter[2 * dstY + 1]; + int chrAlpha = vChrFilter[2 * dstY + 1]; + lumMmxFilter[2] = + lumMmxFilter[3] = vLumFilter[2 * dstY ] * 0x10001; + chrMmxFilter[2] = + chrMmxFilter[3] = vChrFilter[2 * chrDstY] * 0x10001; + yuv2packed2(c, lumSrcPtr, chrUSrcPtr, chrVSrcPtr, + alpPixBuf ? alpSrcPtr : NULL, + dest[0], dstW, lumAlpha, chrAlpha, dstY); + } else { //general RGB + yuv2packedX(c, vLumFilter + dstY * vLumFilterSize, + lumSrcPtr, vLumFilterSize, + vChrFilter + dstY * vChrFilterSize, + chrUSrcPtr, chrVSrcPtr, vChrFilterSize, + alpSrcPtr, dest[0], dstW, dstY); } } } } - return srcSliceH; -} - -int ff_hardcodedcpuflags(void) -{ - int flags = 0; -#if COMPILE_TEMPLATE_MMX2 - flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2; -#elif COMPILE_TEMPLATE_AMD3DNOW - flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_3DNOW; -#elif COMPILE_TEMPLATE_MMX - flags |= SWS_CPU_CAPS_MMX; -#elif COMPILE_TEMPLATE_ALTIVEC - flags |= SWS_CPU_CAPS_ALTIVEC; -#elif ARCH_BFIN - flags |= SWS_CPU_CAPS_BFIN; -#endif - return flags; -} -void ff_get_unscaled_swscale(SwsContext *c) -{ - const enum PixelFormat srcFormat = c->srcFormat; - const enum PixelFormat dstFormat = c->dstFormat; - const int flags = c->flags; - const int dstH = c->dstH; - int needsDither; - - needsDither= isAnyRGB(dstFormat) - && c->dstFormatBpp < 24 - && (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat))); + if (isPlanar(dstFormat) && isALPHA(dstFormat) && !alpPixBuf) + fillPlane(dst[3], dstStride[3], dstW, dstY-lastDstY, lastDstY, 255); - /* yv12_to_nv12 */ - if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) { - c->swScale= planarToNv12Wrapper; - } - /* yuv2bgr */ - if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P || srcFormat==PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) - && !(flags & SWS_ACCURATE_RND) && !(dstH&1)) { - c->swScale= ff_yuv2rgb_get_func_ptr(c); - } - - if (srcFormat==PIX_FMT_YUV410P && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_BITEXACT)) { - c->swScale= yvu9ToYv12Wrapper; - } - - /* bgr24toYV12 */ - if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND)) - c->swScale= bgr24ToYv12Wrapper; - - /* RGB/BGR -> RGB/BGR (no dither needed forms) */ - if ( isAnyRGB(srcFormat) - && isAnyRGB(dstFormat) - && srcFormat != PIX_FMT_BGR8 && dstFormat != PIX_FMT_BGR8 - && srcFormat != PIX_FMT_RGB8 && dstFormat != PIX_FMT_RGB8 - && srcFormat != PIX_FMT_BGR4 && dstFormat != PIX_FMT_BGR4 - && srcFormat != PIX_FMT_RGB4 && dstFormat != PIX_FMT_RGB4 - && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE - && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE - && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK - && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE - && srcFormat != PIX_FMT_RGB48LE && dstFormat != PIX_FMT_RGB48LE - && srcFormat != PIX_FMT_RGB48BE && dstFormat != PIX_FMT_RGB48BE - && srcFormat != PIX_FMT_BGR48LE && dstFormat != PIX_FMT_BGR48LE - && srcFormat != PIX_FMT_BGR48BE && dstFormat != PIX_FMT_BGR48BE - && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) - c->swScale= rgbToRgbWrapper; - - if ((usePal(srcFormat) && ( - dstFormat == PIX_FMT_RGB32 || - dstFormat == PIX_FMT_RGB32_1 || - dstFormat == PIX_FMT_RGB24 || - dstFormat == PIX_FMT_BGR32 || - dstFormat == PIX_FMT_BGR32_1 || - dstFormat == PIX_FMT_BGR24))) - c->swScale= palToRgbWrapper; - - if (srcFormat == PIX_FMT_YUV422P) { - if (dstFormat == PIX_FMT_YUYV422) - c->swScale= yuv422pToYuy2Wrapper; - else if (dstFormat == PIX_FMT_UYVY422) - c->swScale= yuv422pToUyvyWrapper; - } - - /* LQ converters if -sws 0 or -sws 4*/ - if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) { - /* yv12_to_yuy2 */ - if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) { - if (dstFormat == PIX_FMT_YUYV422) - c->swScale= planarToYuy2Wrapper; - else if (dstFormat == PIX_FMT_UYVY422) - c->swScale= planarToUyvyWrapper; - } - } - if(srcFormat == PIX_FMT_YUYV422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P)) - c->swScale= yuyvToYuv420Wrapper; - if(srcFormat == PIX_FMT_UYVY422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P)) - c->swScale= uyvyToYuv420Wrapper; - if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P) - c->swScale= yuyvToYuv422Wrapper; - if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P) - c->swScale= uyvyToYuv422Wrapper; - -#if COMPILE_ALTIVEC - if ((c->flags & SWS_CPU_CAPS_ALTIVEC) && - !(c->flags & SWS_BITEXACT) && - srcFormat == PIX_FMT_YUV420P) { - // unscaled YV12 -> packed YUV, we want speed - if (dstFormat == PIX_FMT_YUYV422) - c->swScale= yv12toyuy2_unscaled_altivec; - else if (dstFormat == PIX_FMT_UYVY422) - c->swScale= yv12touyvy_unscaled_altivec; - } -#endif - - /* simple copy */ - if ( srcFormat == dstFormat - || (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P) - || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P) - || (isPlanarYUV(srcFormat) && isGray(dstFormat)) - || (isPlanarYUV(dstFormat) && isGray(srcFormat)) - || (isGray(dstFormat) && isGray(srcFormat)) - || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) - && c->chrDstHSubSample == c->chrSrcHSubSample - && c->chrDstVSubSample == c->chrSrcVSubSample - && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 - && srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21)) - { - if (isPacked(c->srcFormat)) - c->swScale= packedCopyWrapper; - else /* Planar YUV or gray */ - c->swScale= planarCopyWrapper; - } -#if ARCH_BFIN - if (flags & SWS_CPU_CAPS_BFIN) - ff_bfin_get_unscaled_swscale (c); +#if HAVE_MMX2 + if (av_get_cpu_flags() & AV_CPU_FLAG_MMX2) + __asm__ volatile("sfence":::"memory"); #endif -} + emms_c(); -static void reset_ptr(const uint8_t* src[], int format) -{ - if(!isALPHA(format)) - src[3]=NULL; - if(!isPlanarYUV(format)) { - src[3]=src[2]=NULL; + /* store changed local vars back in the context */ + c->dstY= dstY; + c->lumBufIndex= lumBufIndex; + c->chrBufIndex= chrBufIndex; + c->lastInLumBuf= lastInLumBuf; + c->lastInChrBuf= lastInChrBuf; - if (!usePal(format)) - src[1]= NULL; - } + return dstY - lastDstY; } -static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt, - const int linesizes[4]) +static av_cold void sws_init_swScale_c(SwsContext *c) { - const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; - int i; + enum PixelFormat srcFormat = c->srcFormat; - for (i = 0; i < 4; i++) { - int plane = desc->comp[i].plane; - if (!data[plane] || !linesizes[plane]) - return 0; - } + ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX, + &c->yuv2nv12cX, &c->yuv2packed1, + &c->yuv2packed2, &c->yuv2packedX); - return 1; -} + ff_sws_init_input_funcs(c); -/** - * swscale wrapper, so we don't need to export the SwsContext. - * Assumes planar YUV to be in YUV order instead of YVU. - */ -int sws_scale(SwsContext *c, const uint8_t* const src[], const int srcStride[], int srcSliceY, - int srcSliceH, uint8_t* const dst[], const int dstStride[]) -{ - int i; - const uint8_t* src2[4]= {src[0], src[1], src[2], src[3]}; - uint8_t* dst2[4]= {dst[0], dst[1], dst[2], dst[3]}; - - // do not mess up sliceDir if we have a "trailing" 0-size slice - if (srcSliceH == 0) - return 0; - - if (!check_image_pointers(src, c->srcFormat, srcStride)) { - av_log(c, AV_LOG_ERROR, "bad src image pointers\n"); - return 0; - } - if (!check_image_pointers(dst, c->dstFormat, dstStride)) { - av_log(c, AV_LOG_ERROR, "bad dst image pointers\n"); - return 0; - } - - if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) { - av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n"); - return 0; - } - if (c->sliceDir == 0) { - if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1; + if (c->srcBpc == 8) { + if (c->dstBpc <= 10) { + c->hyScale = c->hcScale = hScale8To15_c; + if (c->flags & SWS_FAST_BILINEAR) { + c->hyscale_fast = hyscale_fast_c; + c->hcscale_fast = hcscale_fast_c; + } + } else { + c->hyScale = c->hcScale = hScale8To19_c; + } + } else { + c->hyScale = c->hcScale = c->dstBpc > 10 ? hScale16To19_c : hScale16To15_c; } - if (usePal(c->srcFormat)) { - for (i=0; i<256; i++) { - int p, r, g, b,y,u,v; - if(c->srcFormat == PIX_FMT_PAL8) { - p=((const uint32_t*)(src[1]))[i]; - r= (p>>16)&0xFF; - g= (p>> 8)&0xFF; - b= p &0xFF; - } else if(c->srcFormat == PIX_FMT_RGB8) { - r= (i>>5 )*36; - g= ((i>>2)&7)*36; - b= (i&3 )*85; - } else if(c->srcFormat == PIX_FMT_BGR8) { - b= (i>>6 )*85; - g= ((i>>3)&7)*36; - r= (i&7 )*36; - } else if(c->srcFormat == PIX_FMT_RGB4_BYTE) { - r= (i>>3 )*255; - g= ((i>>1)&3)*85; - b= (i&1 )*255; - } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_Y400A) { - r = g = b = i; + if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) { + if (c->dstBpc <= 10) { + if (c->srcRange) { + c->lumConvertRange = lumRangeFromJpeg_c; + c->chrConvertRange = chrRangeFromJpeg_c; } else { - assert(c->srcFormat == PIX_FMT_BGR4_BYTE); - b= (i>>3 )*255; - g= ((i>>1)&3)*85; - r= (i&1 )*255; + c->lumConvertRange = lumRangeToJpeg_c; + c->chrConvertRange = chrRangeToJpeg_c; } - y= av_clip_uint8((RY*r + GY*g + BY*b + ( 33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT); - u= av_clip_uint8((RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT); - v= av_clip_uint8((RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT); - c->pal_yuv[i]= y + (u<<8) + (v<<16); - - switch(c->dstFormat) { - case PIX_FMT_BGR32: -#if !HAVE_BIGENDIAN - case PIX_FMT_RGB24: -#endif - c->pal_rgb[i]= r + (g<<8) + (b<<16); - break; - case PIX_FMT_BGR32_1: -#if HAVE_BIGENDIAN - case PIX_FMT_BGR24: -#endif - c->pal_rgb[i]= (r + (g<<8) + (b<<16)) << 8; - break; - case PIX_FMT_RGB32_1: -#if HAVE_BIGENDIAN - case PIX_FMT_RGB24: -#endif - c->pal_rgb[i]= (b + (g<<8) + (r<<16)) << 8; - break; - case PIX_FMT_RGB32: -#if !HAVE_BIGENDIAN - case PIX_FMT_BGR24: -#endif - default: - c->pal_rgb[i]= b + (g<<8) + (r<<16); + } else { + if (c->srcRange) { + c->lumConvertRange = lumRangeFromJpeg16_c; + c->chrConvertRange = chrRangeFromJpeg16_c; + } else { + c->lumConvertRange = lumRangeToJpeg16_c; + c->chrConvertRange = chrRangeToJpeg16_c; } } } - // copy strides, so they can safely be modified - if (c->sliceDir == 1) { - // slices go from top to bottom - int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2], srcStride[3]}; - int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]}; - - reset_ptr(src2, c->srcFormat); - reset_ptr((const uint8_t**)dst2, c->dstFormat); - - /* reset slice direction at end of frame */ - if (srcSliceY + srcSliceH == c->srcH) - c->sliceDir = 0; - - return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, dstStride2); - } else { - // slices go from bottom to top => we flip the image internally - int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2], -srcStride[3]}; - int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2], -dstStride[3]}; - - src2[0] += (srcSliceH-1)*srcStride[0]; - if (!usePal(c->srcFormat)) - src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1]; - src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2]; - src2[3] += (srcSliceH-1)*srcStride[3]; - dst2[0] += ( c->dstH -1)*dstStride[0]; - dst2[1] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1]; - dst2[2] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2]; - dst2[3] += ( c->dstH -1)*dstStride[3]; - - reset_ptr(src2, c->srcFormat); - reset_ptr((const uint8_t**)dst2, c->dstFormat); - - /* reset slice direction at end of frame */ - if (!srcSliceY) - c->sliceDir = 0; - - return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2); - } + if (!(isGray(srcFormat) || isGray(c->dstFormat) || + srcFormat == PIX_FMT_MONOBLACK || srcFormat == PIX_FMT_MONOWHITE)) + c->needs_hcscale = 1; } -/* Convert the palette to the same packed 32-bit format as the palette */ -void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette) +SwsFunc ff_getSwsFunc(SwsContext *c) { - long i; + sws_init_swScale_c(c); - for (i=0; i dst format: ABC */ -void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, long num_pixels, const uint8_t *palette) -{ - long i; - - for (i=0; i