*/
/*
- supported Input formats: YV12, I420, IYUV, YUY2, BGR32, BGR24, BGR16, BGR15, RGB32, RGB24, Y8, Y800
- supported output formats: YV12, I420, IYUV, BGR15, BGR16, BGR24, BGR32, Y8, Y800
- BGR15/16 support dithering
+ supported Input formats: YV12, I420/IYUV, YUY2, BGR32, BGR24, BGR16, BGR15, RGB32, RGB24, Y8/Y800, YVU9/IF09
+ supported output formats: YV12, I420/IYUV, {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 -> BGR15/BGR16/BGR24/BGR32
- YV12/I420/IYUV -> YV12/I420/IYUV
- YUY2/BGR15/BGR16/BGR24/BGR32/RGB24/RGB32 -> same format
+ unscaled special converters (YV12=I420=IYUV, Y800=Y8)
+ YV12 -> {BGR,RGB}{1,4,8,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
- YV12/I420 -> BGR16
+tested special converters (most are tested actually but i didnt write it down ...)
+ YV12 -> BGR16
YV12 -> YV12
BGR15 -> BGR16
BGR16 -> BGR16
+ YVU9 -> YV12
untested special converters
YV12/I420 -> BGR15/BGR24/BGR32 (its the yuv2rgb stuff, so it should be ok)
#define isPlanarYUV(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x)==IMGFMT_YVU9)
#define isYUV(x) ((x)==IMGFMT_YUY2 || isPlanarYUV(x))
#define isGray(x) ((x)==IMGFMT_Y800)
+#define isRGB(x) (((x)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
+#define isBGR(x) (((x)&IMGFMT_BGR_MASK)==IMGFMT_BGR)
#define isSupportedIn(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x)==IMGFMT_YUY2 \
|| (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15\
|| (x)==IMGFMT_RGB32|| (x)==IMGFMT_RGB24\
- || (x)==IMGFMT_Y800)
+ || (x)==IMGFMT_Y800 || (x)==IMGFMT_YVU9)
#define isSupportedOut(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 \
- || (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15\
- || (x)==IMGFMT_Y800)
-#define isRGB(x) (((x)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
-#define isBGR(x) (((x)&IMGFMT_BGR_MASK)==IMGFMT_BGR)
+ || isRGB(x) || isBGR(x)\
+ || (x)==IMGFMT_Y800 || (x)==IMGFMT_YVU9)
#define isPacked(x) ((x)==IMGFMT_YUY2 || isRGB(x) || isBGR(x))
#define RGB2YUV_SHIFT 16
static const uint64_t bgr2YOffset __attribute__((aligned(8))) = 0x1010101010101010ULL;
static const uint64_t bgr2UVOffset __attribute__((aligned(8)))= 0x8080808080808080ULL;
static const uint64_t w1111 __attribute__((aligned(8))) = 0x0001000100010001ULL;
-
-// FIXME remove
-static uint64_t __attribute__((aligned(8))) asm_yalpha1;
-static uint64_t __attribute__((aligned(8))) asm_uvalpha1;
#endif
// clipping helper table for C implementations:
static unsigned char clip_table[768];
-static unsigned short clip_table16b[768];
-static unsigned short clip_table16g[768];
-static unsigned short clip_table16r[768];
-static unsigned short clip_table15b[768];
-static unsigned short clip_table15g[768];
-static unsigned short clip_table15r[768];
-
-// yuv->rgb conversion tables:
-static int yuvtab_2568[256];
-static int yuvtab_3343[256];
-static int yuvtab_0c92[256];
-static int yuvtab_1a1e[256];
-static int yuvtab_40cf[256];
-// Needed for cubic scaler to catch overflows
-static int clip_yuvtab_2568[768];
-static int clip_yuvtab_3343[768];
-static int clip_yuvtab_0c92[768];
-static int clip_yuvtab_1a1e[768];
-static int clip_yuvtab_40cf[768];
-
//global sws_flags from the command line
int sws_flags=2;
int srcSliceH, uint8_t* dst[], int dstStride[])=NULL;
static SwsVector *getConvVec(SwsVector *a, SwsVector *b);
+static inline void orderYUV(int format, uint8_t * sortedP[], int sortedStride[], uint8_t * p[], int stride[]);
+void *yuv2rgb_c_init (unsigned bpp, int mode, void *table_rV[256], void *table_gU[256], int table_gV[256], void *table_bU[256]);
+
+extern const uint8_t dither_2x2_4[2][8];
+extern const uint8_t dither_2x2_8[2][8];
+extern const uint8_t dither_8x8_32[8][8];
+extern const uint8_t dither_8x8_73[8][8];
+extern const uint8_t dither_8x8_220[8][8];
#ifdef CAN_COMPILE_X86_ASM
void in_asm_used_var_warning_killer()
{
volatile int i= yCoeff+vrCoeff+ubCoeff+vgCoeff+ugCoeff+bF8+bFC+w400+w80+w10+
- bm00001111+bm00000111+bm11111000+b16Mask+g16Mask+r16Mask+b15Mask+g15Mask+r15Mask+asm_yalpha1+ asm_uvalpha1+
+ bm00001111+bm00000111+bm11111000+b16Mask+g16Mask+r16Mask+b15Mask+g15Mask+r15Mask+
M24A+M24B+M24C+w02 + b5Dither+g5Dither+r5Dither+g6Dither+dither4[0]+dither8[0]+bm01010101;
if(i) i=0;
}
#endif
static int testFormat[]={
+IMGFMT_YVU9,
IMGFMT_YV12,
//IMGFMT_IYUV,
IMGFMT_I420,
IMGFMT_BGR16,
IMGFMT_BGR24,
IMGFMT_BGR32,
+IMGFMT_RGB24,
+IMGFMT_RGB32,
//IMGFMT_Y8,
IMGFMT_Y800,
//IMGFMT_YUY2,
SwsContext *srcContext, *dstContext, *outContext;
for(i=0; i<3; i++){
- srcStride[i]= srcW*4;
- dstStride[i]= dstW*4;
+ // avoid stride % bpp != 0
+ if(srcFormat==IMGFMT_RGB24 || srcFormat==IMGFMT_BGR24)
+ srcStride[i]= srcW*3;
+ else
+ srcStride[i]= srcW*4;
+
+ if(dstFormat==IMGFMT_RGB24 || dstFormat==IMGFMT_BGR24)
+ dstStride[i]= dstW*3;
+ else
+ dstStride[i]= dstW*4;
+
src[i]= malloc(srcStride[i]*srcH);
dst[i]= malloc(dstStride[i]*dstH);
out[i]= malloc(refStride[i]*h);
ssdU/= w*h/4;
ssdV/= w*h/4;
- if(ssdY>10 || ssdU>10 || ssdV>10){
+ if(ssdY>100 || ssdU>50 || ssdV>50){
printf(" %s %dx%d -> %s %4dx%4d flags=%2d SSD=%5lld,%5lld,%5lld\n",
vo_format_name(srcFormat), srcW, srcH,
vo_format_name(dstFormat), dstW, dstH,
dstFormat= testFormat[dstFormatIndex];
if(!dstFormat) break;
if(!isSupportedOut(dstFormat)) continue;
+printf("%s -> %s\n",
+ vo_format_name(srcFormat),
+ vo_format_name(dstFormat));
srcW= w+w/3;
srcH= h+h/3;
static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
- uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW)
+ uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW, int chrDstW)
{
//FIXME Optimize (just quickly writen not opti..)
int i;
}
if(uDest != NULL)
- for(i=0; i<(dstW>>1); i++)
+ for(i=0; i<chrDstW; i++)
{
int u=0;
int v=0;
}
}
-static inline void yuv2rgbXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
+#define YSCALE_YUV_2_RGBX_C(type) \
+ for(i=0; i<(dstW>>1); i++){\
+ int j;\
+ int Y1=0;\
+ int Y2=0;\
+ int U=0;\
+ int V=0;\
+ type *r, *b, *g;\
+ const int i2= 2*i;\
+ \
+ for(j=0; j<lumFilterSize; j++)\
+ {\
+ Y1 += lumSrc[j][i2] * lumFilter[j];\
+ Y2 += lumSrc[j][i2+1] * lumFilter[j];\
+ }\
+ for(j=0; j<chrFilterSize; j++)\
+ {\
+ U += chrSrc[j][i] * chrFilter[j];\
+ V += chrSrc[j][i+2048] * chrFilter[j];\
+ }\
+ Y1>>=19;\
+ Y2>>=19;\
+ U >>=19;\
+ V >>=19;\
+ 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;\
+ }\
+ r = c->table_rV[V];\
+ g = c->table_gU[U] + c->table_gV[V];\
+ b = c->table_bU[U];\
+
+#define YSCALE_YUV_2_RGB2_C(type) \
+ 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+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>19;\
+ type *r, *b, *g;\
+ r = c->table_rV[V];\
+ g = c->table_gU[U] + c->table_gV[V];\
+ b = c->table_bU[U];\
+
+#define YSCALE_YUV_2_RGB1_C(type) \
+ 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+2048])>>7;\
+ type *r, *b, *g;\
+ r = c->table_rV[V];\
+ g = c->table_gU[U] + c->table_gV[V];\
+ b = c->table_bU[U];\
+
+#define YSCALE_YUV_2_RGB1B_C(type) \
+ 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+2048] + uvbuf1[i+2048])>>8;\
+ type *r, *b, *g;\
+ r = c->table_rV[V];\
+ g = c->table_gU[U] + c->table_gV[V];\
+ b = c->table_bU[U];\
+
+#define YSCALE_YUV_2_ANYRGB_C(func)\
+ switch(c->dstFormat)\
+ {\
+ case IMGFMT_BGR32:\
+ case IMGFMT_RGB32:\
+ func(uint32_t)\
+ ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\
+ ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\
+ } \
+ break;\
+ case IMGFMT_RGB24:\
+ func(uint8_t)\
+ ((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];\
+ ((uint8_t*)dest)+=6;\
+ }\
+ break;\
+ case IMGFMT_BGR24:\
+ func(uint8_t)\
+ ((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];\
+ ((uint8_t*)dest)+=6;\
+ }\
+ break;\
+ case IMGFMT_RGB16:\
+ case IMGFMT_BGR16:\
+ {\
+ 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)\
+ ((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 IMGFMT_RGB15:\
+ case IMGFMT_BGR15:\
+ {\
+ 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)\
+ ((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 IMGFMT_RGB8:\
+ case IMGFMT_BGR8:\
+ {\
+ const uint8_t * const d64= dither_8x8_73[y&7];\
+ const uint8_t * const d32= dither_8x8_32[y&7];\
+ func(uint8_t)\
+ ((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 IMGFMT_RGB4:\
+ case IMGFMT_BGR4:\
+ {\
+ const uint8_t * const d64= dither_8x8_73 [y&7];\
+ const uint8_t * const d128=dither_8x8_220[y&7];\
+ func(uint8_t)\
+ ((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 IMGFMT_RGB1:\
+ case IMGFMT_BGR1:\
+ {\
+ 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<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]= acc;\
+ ((uint8_t*)dest)++;\
+ }\
+\
+/*\
+((uint8_t*)dest)-= dstW>>4;\
+{\
+ int acc=0;\
+ int left=0;\
+ static int top[1024];\
+ static int last_new[1024][1024];\
+ static int last_in3[1024][1024];\
+ static int drift[1024][1024];\
+ int topLeft=0;\
+ int shift=0;\
+ int count=0;\
+ const uint8_t * const d128=dither_8x8_220[y&7];\
+ int error_new=0;\
+ int error_in3=0;\
+ int f=0;\
+ \
+ for(i=dstW>>1; i<dstW; i++){\
+ int in= ((buf0[i ]*yalpha1+buf1[i ]*yalpha)>>19);\
+ int in2 = (76309 * (in - 16) + 32768) >> 16;\
+ int in3 = (in2 < 0) ? 0 : ((in2 > 255) ? 255 : in2);\
+ int old= (left*7 + topLeft + top[i]*5 + top[i+1]*3)/20 + in3\
+ + (last_new[y][i] - in3)*f/256;\
+ int new= old> 128 ? 255 : 0;\
+\
+ error_new+= ABS(last_new[y][i] - new);\
+ error_in3+= ABS(last_in3[y][i] - in3);\
+ f= error_new - error_in3*4;\
+ if(f<0) f=0;\
+ if(f>256) f=256;\
+\
+ topLeft= top[i];\
+ left= top[i]= old - new;\
+ last_new[y][i]= new;\
+ last_in3[y][i]= in3;\
+\
+ acc+= acc + (new&1);\
+ if((i&7)==6){\
+ ((uint8_t*)dest)[0]= acc;\
+ ((uint8_t*)dest)++;\
+ }\
+ }\
+}\
+*/\
+ }\
+ break;\
+ }\
+
+
+static inline void yuv2rgbXinC(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
- uint8_t *dest, int dstW, int dstFormat)
+ uint8_t *dest, int dstW, int y)
{
- if(dstFormat==IMGFMT_BGR32)
+ int i;
+ switch(c->dstFormat)
{
- int i;
-#ifdef WORDS_BIGENDIAN
- dest++;
-#endif
- for(i=0; i<(dstW>>1); i++){
- int j;
- int Y1=0;
- int Y2=0;
- int U=0;
- int V=0;
- int Cb, Cr, Cg;
- for(j=0; j<lumFilterSize; j++)
- {
- Y1 += lumSrc[j][2*i] * lumFilter[j];
- Y2 += lumSrc[j][2*i+1] * lumFilter[j];
- }
- for(j=0; j<chrFilterSize; j++)
- {
- U += chrSrc[j][i] * chrFilter[j];
- V += chrSrc[j][i+2048] * chrFilter[j];
- }
- Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];
- Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];
- U >>= 19;
- V >>= 19;
-
- Cb= clip_yuvtab_40cf[U+ 256];
- Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];
- Cr= clip_yuvtab_3343[V+ 256];
-
- dest[8*i+0]=clip_table[((Y1 + Cb) >>13)];
- dest[8*i+1]=clip_table[((Y1 + Cg) >>13)];
- dest[8*i+2]=clip_table[((Y1 + Cr) >>13)];
-
- dest[8*i+4]=clip_table[((Y2 + Cb) >>13)];
- dest[8*i+5]=clip_table[((Y2 + Cg) >>13)];
- dest[8*i+6]=clip_table[((Y2 + Cr) >>13)];
+ case IMGFMT_RGB32:
+ case IMGFMT_BGR32:
+ YSCALE_YUV_2_RGBX_C(uint32_t)
+ ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];
+ ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];
}
- }
- else if(dstFormat==IMGFMT_BGR24)
- {
- int i;
- for(i=0; i<(dstW>>1); i++){
- int j;
- int Y1=0;
- int Y2=0;
- int U=0;
- int V=0;
- int Cb, Cr, Cg;
- for(j=0; j<lumFilterSize; j++)
- {
- Y1 += lumSrc[j][2*i] * lumFilter[j];
- Y2 += lumSrc[j][2*i+1] * lumFilter[j];
- }
- for(j=0; j<chrFilterSize; j++)
- {
- U += chrSrc[j][i] * chrFilter[j];
- V += chrSrc[j][i+2048] * chrFilter[j];
+ break;
+ case IMGFMT_RGB24:
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((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];
+ ((uint8_t*)dest)+=6;
+ }
+ break;
+ case IMGFMT_BGR24:
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((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];
+ ((uint8_t*)dest)+=6;
+ }
+ break;
+ case IMGFMT_RGB16:
+ case IMGFMT_BGR16:
+ {
+ 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];
+ YSCALE_YUV_2_RGBX_C(uint16_t)
+ ((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];
}
- Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];
- Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];
- U >>= 19;
- V >>= 19;
-
- Cb= clip_yuvtab_40cf[U+ 256];
- Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];
- Cr= clip_yuvtab_3343[V+ 256];
-
- dest[0]=clip_table[((Y1 + Cb) >>13)];
- dest[1]=clip_table[((Y1 + Cg) >>13)];
- dest[2]=clip_table[((Y1 + Cr) >>13)];
-
- dest[3]=clip_table[((Y2 + Cb) >>13)];
- dest[4]=clip_table[((Y2 + Cg) >>13)];
- dest[5]=clip_table[((Y2 + Cr) >>13)];
- dest+=6;
}
- }
- else if(dstFormat==IMGFMT_BGR16)
- {
- int i;
-#ifdef DITHER1XBPP
- static int ditherb1=1<<14;
- static int ditherg1=1<<13;
- static int ditherr1=2<<14;
- static int ditherb2=3<<14;
- static int ditherg2=3<<13;
- static int ditherr2=0<<14;
-
- ditherb1 ^= (1^2)<<14;
- ditherg1 ^= (1^2)<<13;
- ditherr1 ^= (1^2)<<14;
- ditherb2 ^= (3^0)<<14;
- ditherg2 ^= (3^0)<<13;
- ditherr2 ^= (3^0)<<14;
-#else
- const int ditherb1=0;
- const int ditherg1=0;
- const int ditherr1=0;
- const int ditherb2=0;
- const int ditherg2=0;
- const int ditherr2=0;
-#endif
- for(i=0; i<(dstW>>1); i++){
- int j;
- int Y1=0;
- int Y2=0;
- int U=0;
- int V=0;
- int Cb, Cr, Cg;
- for(j=0; j<lumFilterSize; j++)
- {
- Y1 += lumSrc[j][2*i] * lumFilter[j];
- Y2 += lumSrc[j][2*i+1] * lumFilter[j];
+ break;
+ case IMGFMT_RGB15:
+ case IMGFMT_BGR15:
+ {
+ 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];
+ YSCALE_YUV_2_RGBX_C(uint16_t)
+ ((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];
}
- for(j=0; j<chrFilterSize; j++)
- {
- U += chrSrc[j][i] * chrFilter[j];
- V += chrSrc[j][i+2048] * chrFilter[j];
+ }
+ break;
+ case IMGFMT_RGB8:
+ case IMGFMT_BGR8:
+ {
+ const uint8_t * const d64= dither_8x8_73[y&7];
+ const uint8_t * const d32= dither_8x8_32[y&7];
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((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]];
}
- Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];
- Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];
- U >>= 19;
- V >>= 19;
-
- Cb= clip_yuvtab_40cf[U+ 256];
- Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];
- Cr= clip_yuvtab_3343[V+ 256];
-
- ((uint16_t*)dest)[2*i] =
- clip_table16b[(Y1 + Cb + ditherb1) >>13] |
- clip_table16g[(Y1 + Cg + ditherg1) >>13] |
- clip_table16r[(Y1 + Cr + ditherr1) >>13];
-
- ((uint16_t*)dest)[2*i+1] =
- clip_table16b[(Y2 + Cb + ditherb2) >>13] |
- clip_table16g[(Y2 + Cg + ditherg2) >>13] |
- clip_table16r[(Y2 + Cr + ditherr2) >>13];
}
- }
- else if(dstFormat==IMGFMT_BGR15)
- {
- int i;
-#ifdef DITHER1XBPP
- static int ditherb1=1<<14;
- static int ditherg1=1<<14;
- static int ditherr1=2<<14;
- static int ditherb2=3<<14;
- static int ditherg2=3<<14;
- static int ditherr2=0<<14;
-
- ditherb1 ^= (1^2)<<14;
- ditherg1 ^= (1^2)<<14;
- ditherr1 ^= (1^2)<<14;
- ditherb2 ^= (3^0)<<14;
- ditherg2 ^= (3^0)<<14;
- ditherr2 ^= (3^0)<<14;
-#else
- const int ditherb1=0;
- const int ditherg1=0;
- const int ditherr1=0;
- const int ditherb2=0;
- const int ditherg2=0;
- const int ditherr2=0;
-#endif
- for(i=0; i<(dstW>>1); i++){
- int j;
- int Y1=0;
- int Y2=0;
- int U=0;
- int V=0;
- int Cb, Cr, Cg;
- for(j=0; j<lumFilterSize; j++)
- {
- Y1 += lumSrc[j][2*i] * lumFilter[j];
- Y2 += lumSrc[j][2*i+1] * lumFilter[j];
+ break;
+ case IMGFMT_RGB4:
+ case IMGFMT_BGR4:
+ {
+ const uint8_t * const d64= dither_8x8_73 [y&7];
+ const uint8_t * const d128=dither_8x8_220[y&7];
+ YSCALE_YUV_2_RGBX_C(uint8_t)
+ ((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]];
}
- for(j=0; j<chrFilterSize; j++)
- {
- U += chrSrc[j][i] * chrFilter[j];
- V += chrSrc[j][i+2048] * chrFilter[j];
+ }
+ break;
+ case IMGFMT_RGB1:
+ case IMGFMT_BGR1:
+ {
+ 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<dstW-1; i+=2){
+ int j;
+ int Y1=0;
+ int Y2=0;
+
+ for(j=0; j<lumFilterSize; j++)
+ {
+ Y1 += lumSrc[j][i] * lumFilter[j];
+ Y2 += lumSrc[j][i+1] * lumFilter[j];
+ }
+ Y1>>=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]= acc;
+ ((uint8_t*)dest)++;
+ }
}
- Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];
- Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];
- U >>= 19;
- V >>= 19;
-
- Cb= clip_yuvtab_40cf[U+ 256];
- Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];
- Cr= clip_yuvtab_3343[V+ 256];
-
- ((uint16_t*)dest)[2*i] =
- clip_table15b[(Y1 + Cb + ditherb1) >>13] |
- clip_table15g[(Y1 + Cg + ditherg1) >>13] |
- clip_table15r[(Y1 + Cr + ditherr1) >>13];
-
- ((uint16_t*)dest)[2*i+1] =
- clip_table15b[(Y2 + Cb + ditherb2) >>13] |
- clip_table15g[(Y2 + Cg + ditherg2) >>13] |
- clip_table15r[(Y2 + Cr + ditherr2) >>13];
}
+ break;
}
}
context->swScale(context, src, srcStride, srcSliceY, srcSliceH, dst, dstStride3);
}
-// will use sws_flags & src_filter (from cmd line)
-SwsContext *getSwsContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
+void swsGetFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam)
{
- int flags=0;
static int firstTime=1;
+ *flags=0;
#ifdef ARCH_X86
if(gCpuCaps.hasMMX)
if(firstTime)
{
firstTime=0;
- flags= SWS_PRINT_INFO;
+ *flags= SWS_PRINT_INFO;
}
- else if(verbose>1) flags= SWS_PRINT_INFO;
+ else if(verbose>1) *flags= SWS_PRINT_INFO;
if(src_filter.lumH) freeVec(src_filter.lumH);
if(src_filter.lumV) freeVec(src_filter.lumV);
switch(sws_flags)
{
- case 0: flags|= SWS_FAST_BILINEAR; break;
- case 1: flags|= SWS_BILINEAR; break;
- case 2: flags|= SWS_BICUBIC; break;
- case 3: flags|= SWS_X; break;
- case 4: flags|= SWS_POINT; break;
- case 5: flags|= SWS_AREA; break;
- default:flags|= SWS_BILINEAR; break;
+ case 0: *flags|= SWS_FAST_BILINEAR; break;
+ case 1: *flags|= SWS_BILINEAR; break;
+ case 2: *flags|= SWS_BICUBIC; break;
+ case 3: *flags|= SWS_X; break;
+ case 4: *flags|= SWS_POINT; break;
+ case 5: *flags|= SWS_AREA; break;
+ case 6: *flags|= SWS_BICUBLIN; break;
+ default:*flags|= SWS_BILINEAR; break;
}
+
+ *srcFilterParam= &src_filter;
+ *dstFilterParam= NULL;
+}
+
+// will use sws_flags & src_filter (from cmd line)
+SwsContext *getSwsContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
+{
+ int flags;
+ SwsFilter *dstFilterParam, *srcFilterParam;
+ swsGetFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam);
- return getSwsContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, &src_filter, NULL);
+ return getSwsContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, srcFilterParam, dstFilterParam);
}
for(i=0; i<768; i++){
int c= MIN(MAX(i-256, 0), 255);
clip_table[i]=c;
- yuvtab_2568[c]= clip_yuvtab_2568[i]=(0x2568*(c-16))+(256<<13);
- yuvtab_3343[c]= clip_yuvtab_3343[i]=0x3343*(c-128);
- yuvtab_0c92[c]= clip_yuvtab_0c92[i]=-0x0c92*(c-128);
- yuvtab_1a1e[c]= clip_yuvtab_1a1e[i]=-0x1a1e*(c-128);
- yuvtab_40cf[c]= clip_yuvtab_40cf[i]=0x40cf*(c-128);
- }
-
- for(i=0; i<768; i++)
- {
- int v= clip_table[i];
- clip_table16b[i]= v>>3;
- clip_table16g[i]= (v<<3)&0x07E0;
- clip_table16r[i]= (v<<8)&0xF800;
- clip_table15b[i]= v>>3;
- clip_table15g[i]= (v<<2)&0x03E0;
- clip_table15r[i]= (v<<7)&0x7C00;
}
cpuCaps= gCpuCaps;
yv12toyuy2( src[0],src[2],src[1],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0] );
}
-static void bgr24to32Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*3==srcStride[0]*4)
- rgb24to32(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for(i=0; i<srcSliceH; i++)
- {
- rgb24to32(srcPtr, dstPtr, c->srcW*3);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
- }
- }
-}
-
-static void bgr24to16Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*3==srcStride[0]*2)
- rgb24to16(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for(i=0; i<srcSliceH; i++)
- {
- rgb24to16(srcPtr, dstPtr, c->srcW*3);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
+/* {RGB,BGR}{15,16,24,32} -> {RGB,BGR}{15,16,24,32} */
+static void rgb2rgbWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ const int srcFormat= c->srcFormat;
+ const int dstFormat= c->dstFormat;
+ const int srcBpp= ((srcFormat&0xFF) + 7)>>3;
+ const int dstBpp= ((dstFormat&0xFF) + 7)>>3;
+ const int srcId= (srcFormat&0xFF)>>2; // 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8
+ const int dstId= (dstFormat&0xFF)>>2;
+ void (*conv)(const uint8_t *src, uint8_t *dst, unsigned src_size)=NULL;
+
+ /* BGR -> BGR */
+ if(isBGR(srcFormat) && isBGR(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;
+ default: MSG_ERR("swScaler: internal error %s -> %s converter\n",
+ vo_format_name(srcFormat), vo_format_name(dstFormat)); break;
}
- }
-}
-
-static void bgr24to15Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*3==srcStride[0]*2)
- rgb24to15(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for(i=0; i<srcSliceH; i++)
- {
- rgb24to15(srcPtr, dstPtr, c->srcW*3);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
- }
- }
-}
-
-static void bgr32to24Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*4==srcStride[0]*3)
- rgb32to24(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for(i=0; i<srcSliceH; i++)
- {
- rgb32to24(srcPtr, dstPtr, c->srcW<<2);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
+ }else if(isBGR(srcFormat) && isRGB(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;
+ case 0x88: conv= rgb32tobgr32; break;
+ default: MSG_ERR("swScaler: internal error %s -> %s converter\n",
+ vo_format_name(srcFormat), vo_format_name(dstFormat)); break;
}
- }
-}
-
-static void bgr32to16Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*4==srcStride[0]*2)
- rgb32to16(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for(i=0; i<srcSliceH; i++)
- {
- rgb32to16(srcPtr, dstPtr, c->srcW<<2);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
+ }else if(isRGB(srcFormat) && isRGB(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;
+ default: MSG_ERR("swScaler: internal error %s -> %s converter\n",
+ vo_format_name(srcFormat), vo_format_name(dstFormat)); break;
}
- }
-}
-
-static void bgr32to15Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*4==srcStride[0]*2)
- rgb32to15(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for(i=0; i<srcSliceH; i++)
- {
- rgb32to15(srcPtr, dstPtr, c->srcW<<2);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
+ }else if(isRGB(srcFormat) && isBGR(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;
+ case 0x88: conv= rgb32tobgr32; break;
+ default: MSG_ERR("swScaler: internal error %s -> %s converter\n",
+ vo_format_name(srcFormat), vo_format_name(dstFormat)); break;
}
- }
-}
-
-static void bgr15to16Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]==srcStride[0])
- rgb15to16(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for(i=0; i<srcSliceH; i++)
- {
- rgb15to16(srcPtr, dstPtr, c->srcW<<1);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
- }
- }
-}
-
-static void bgr15to24Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*2==srcStride[0]*3)
- rgb15to24(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
+ }
+ if(dstStride[0]*srcBpp == srcStride[0]*dstBpp)
+ conv(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
else
{
int i;
for(i=0; i<srcSliceH; i++)
{
- rgb15to24(srcPtr, dstPtr, c->srcW<<1);
+ conv(srcPtr, dstPtr, c->srcW*srcBpp);
srcPtr+= srcStride[0];
dstPtr+= dstStride[0];
}
}
}
-static void bgr15to32Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+static void bgr24toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*2==srcStride[0]*4)
- rgb15to32(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
- for(i=0; i<srcSliceH; i++)
- {
- rgb15to32(srcPtr, dstPtr, c->srcW<<1);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
- }
- }
+ 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]);
}
-static void bgr16to24Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+static void yvu9toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*2==srcStride[0]*3)
- rgb16to24(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
- uint8_t *srcPtr= src[0];
- uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
-
- for(i=0; i<srcSliceH; i++)
- {
- rgb16to24(srcPtr, dstPtr, c->srcW<<1);
- srcPtr+= srcStride[0];
- dstPtr+= dstStride[0];
- }
- }
-}
+ int i;
-static void bgr16to32Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
- int srcSliceH, uint8_t* dst[], int dstStride[]){
-
- if(dstStride[0]*2==srcStride[0]*4)
- rgb16to32(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
- else
- {
- int i;
+ /* copy Y */
+ if(srcStride[0]==dstStride[0])
+ memcpy(dst[0]+ srcSliceY*dstStride[0], src[0], srcStride[0]*srcSliceH);
+ else{
uint8_t *srcPtr= src[0];
uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
for(i=0; i<srcSliceH; i++)
{
- rgb16to32(srcPtr, dstPtr, c->srcW<<1);
+ memcpy(dstPtr, srcPtr, c->srcW);
srcPtr+= srcStride[0];
dstPtr+= dstStride[0];
}
- }
-}
-
-static void bgr24toyv12Wrapper(SwsContext *c, 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(c->dstFormat==IMGFMT_YV12){
+ planar2x(src[1], dst[1], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[1]);
+ planar2x(src[2], dst[2], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[2]);
+ }else{
+ planar2x(src[1], dst[2], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[2]);
+ planar2x(src[2], dst[1], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[1]);
+ }
}
/**
* bring pointers in YUV order instead of YVU
*/
static inline void orderYUV(int format, uint8_t * sortedP[], int sortedStride[], uint8_t * p[], int stride[]){
- if(format == IMGFMT_YV12){
+ if(format == IMGFMT_YV12 || format == IMGFMT_YVU9){
sortedP[0]= p[0];
sortedP[1]= p[1];
sortedP[2]= p[2];
sortedStride[1]=
sortedStride[2]= 0;
}
- else /* I420 */
+ else if(format == IMGFMT_I420)
{
sortedP[0]= p[0];
sortedP[1]= p[2];
sortedStride[0]= stride[0];
sortedStride[1]= stride[2];
sortedStride[2]= stride[1];
+ }else{
+ MSG_ERR("internal error in orderYUV\n");
}
}
int plane;
for(plane=0; plane<3; plane++)
{
- int length= plane==0 ? c->srcW : ((c->srcW+1)>>1);
- int y= plane==0 ? srcSliceY: ((srcSliceY+1)>>1);
- int height= plane==0 ? srcSliceH: ((srcSliceH+1)>>1);
+ int length= plane==0 ? c->srcW : -((-c->srcW )>>c->chrDstHSubSample);
+ int y= plane==0 ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
+ int height= plane==0 ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
if((isGray(c->srcFormat) || isGray(c->dstFormat)) && plane>0)
{
if(!isGray(c->dstFormat))
- memset(dst[plane], 0, dstStride[plane]*height);
+ memset(dst[plane], 128, dstStride[plane]*height);
}
else
{
{
case IMGFMT_IYUV: return IMGFMT_I420;
case IMGFMT_Y8 : return IMGFMT_Y800;
+ case IMGFMT_IF09: return IMGFMT_YVU9;
default: return fourcc;
}
}
break;
case IMGFMT_YV12:
case IMGFMT_I420:
+ case IMGFMT_Y800: //FIXME remove after different subsamplings are fully implemented
*h=1;
*v=1;
break;
SwsContext *c;
int i;
int usesFilter;
- int unscaled;
+ int unscaled, needsDither;
SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};
#ifdef ARCH_X86
if(gCpuCaps.hasMMX)
asm volatile("emms\n\t"::: "memory");
#endif
if(swScale==NULL) globalInit();
-
+//srcFormat= IMGFMT_Y800;
+//dstFormat= IMGFMT_Y800;
/* avoid dupplicate Formats, so we dont need to check to much */
srcFormat = remove_dup_fourcc(srcFormat);
dstFormat = remove_dup_fourcc(dstFormat);
unscaled = (srcW == dstW && srcH == dstH);
+ needsDither= (isBGR(dstFormat) || isRGB(dstFormat))
+ && (dstFormat&0xFF)<24
+ && ((dstFormat&0xFF)<(srcFormat&0xFF) || (!(isRGB(srcFormat) || isBGR(srcFormat))));
if(!isSupportedIn(srcFormat))
{
if(srcFilter->lumH!=NULL && srcFilter->lumH->length>1) usesFilter=1;
if(srcFilter->chrV!=NULL && srcFilter->chrV->length>1) usesFilter=1;
if(srcFilter->chrH!=NULL && srcFilter->chrH->length>1) usesFilter=1;
+
+ getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
+ getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
+
+ // reuse chroma for 2 pixles rgb/bgr unless user wants full chroma interpolation
+ if((isBGR(dstFormat) || isRGB(dstFormat)) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1;
+
+ // drop some chroma lines if the user wants it
+ c->vChrDrop= (flags&SWS_SRC_V_CHR_DROP_MASK)>>SWS_SRC_V_CHR_DROP_SHIFT;
+ c->chrSrcVSubSample+= c->vChrDrop;
+
+ // drop every 2. pixel for chroma calculation unless user wants full chroma
+ if((isBGR(srcFormat) || isRGB(srcFormat)) && !(flags&SWS_FULL_CHR_H_INP))
+ c->chrSrcHSubSample=1;
+
+ c->chrIntHSubSample= c->chrDstHSubSample;
+ c->chrIntVSubSample= c->chrSrcVSubSample;
+
+ // note the -((-x)>>y) is so that we allways round toward +inf
+ c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample);
+ c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample);
+ c->chrDstW= -((-dstW) >> c->chrDstHSubSample);
+ c->chrDstH= -((-dstH) >> c->chrDstVSubSample);
+ if(isBGR(dstFormat))
+ c->yuvTable= yuv2rgb_c_init(dstFormat & 0xFF, MODE_RGB, c->table_rV, c->table_gU, c->table_gV, c->table_bU);
+ if(isRGB(dstFormat))
+ c->yuvTable= yuv2rgb_c_init(dstFormat & 0xFF, MODE_BGR, c->table_rV, c->table_gU, c->table_gV, c->table_bU);
+
/* unscaled special Cases */
if(unscaled && !usesFilter)
{
return c;
}
/* yuv2bgr */
- if(isPlanarYUV(srcFormat) && isBGR(dstFormat))
+ if((srcFormat==IMGFMT_YV12 || srcFormat==IMGFMT_I420) && isBGR(dstFormat))
{
// FIXME multiple yuv2rgb converters wont work that way cuz that thing is full of globals&statics
+ //FIXME rgb vs. bgr ?
#ifdef WORDS_BIGENDIAN
if(dstFormat==IMGFMT_BGR32)
yuv2rgb_init( dstFormat&0xFF /* =bpp */, MODE_BGR);
vo_format_name(srcFormat), vo_format_name(dstFormat));
return c;
}
-
+
/* simple copy */
- if(srcFormat == dstFormat
- || ((isPlanarYUV(srcFormat)||isGray(srcFormat)) && (isPlanarYUV(dstFormat)||isGray(dstFormat))))
+ if( srcFormat == dstFormat
+ || (srcFormat==IMGFMT_YV12 && dstFormat==IMGFMT_I420)
+ || (srcFormat==IMGFMT_I420 && dstFormat==IMGFMT_YV12)
+ || (isPlanarYUV(srcFormat) && isGray(dstFormat))
+ || (isPlanarYUV(dstFormat) && isGray(srcFormat))
+ )
{
c->swScale= simpleCopy;
vo_format_name(srcFormat), vo_format_name(dstFormat));
return c;
}
-
- /* bgr32to24 & rgb32to24*/
- if((srcFormat==IMGFMT_BGR32 && dstFormat==IMGFMT_BGR24)
- ||(srcFormat==IMGFMT_RGB32 && dstFormat==IMGFMT_RGB24))
- {
- c->swScale= bgr32to24Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr32to16 & rgb32to16*/
- if((srcFormat==IMGFMT_BGR32 && dstFormat==IMGFMT_BGR16)
- ||(srcFormat==IMGFMT_RGB32 && dstFormat==IMGFMT_RGB16))
- {
- c->swScale= bgr32to16Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr32to15 & rgb32to15*/
- if((srcFormat==IMGFMT_BGR32 && dstFormat==IMGFMT_BGR15)
- ||(srcFormat==IMGFMT_RGB32 && dstFormat==IMGFMT_RGB15))
- {
- c->swScale= bgr32to15Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
- /* bgr24to32 & rgb24to32*/
- if((srcFormat==IMGFMT_BGR24 && dstFormat==IMGFMT_BGR32)
- ||(srcFormat==IMGFMT_RGB24 && dstFormat==IMGFMT_RGB32))
- {
- c->swScale= bgr24to32Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr24to16 & rgb24to16*/
- if((srcFormat==IMGFMT_BGR24 && dstFormat==IMGFMT_BGR16)
- ||(srcFormat==IMGFMT_RGB24 && dstFormat==IMGFMT_RGB16))
+ if( srcFormat==IMGFMT_YVU9 && (dstFormat==IMGFMT_YV12 || dstFormat==IMGFMT_I420) )
{
- c->swScale= bgr24to16Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr24to15 & rgb24to15*/
- if((srcFormat==IMGFMT_BGR24 && dstFormat==IMGFMT_BGR15)
- ||(srcFormat==IMGFMT_RGB24 && dstFormat==IMGFMT_RGB15))
- {
- c->swScale= bgr24to15Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr15to16 */
- if(srcFormat==IMGFMT_BGR15 && dstFormat==IMGFMT_BGR16)
- {
- c->swScale= bgr15to16Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr15to24 */
- if((srcFormat==IMGFMT_BGR15 && dstFormat==IMGFMT_BGR24)
- ||(srcFormat==IMGFMT_RGB15 && dstFormat==IMGFMT_RGB24))
- {
- c->swScale= bgr15to24Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr15to32 */
- if((srcFormat==IMGFMT_BGR15 && dstFormat==IMGFMT_BGR32)
- ||(srcFormat==IMGFMT_RGB15 && dstFormat==IMGFMT_RGB32))
- {
- c->swScale= bgr15to32Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr16to24 */
- if((srcFormat==IMGFMT_BGR16 && dstFormat==IMGFMT_BGR24)
- ||(srcFormat==IMGFMT_RGB16 && dstFormat==IMGFMT_RGB24))
- {
- c->swScale= bgr16to24Wrapper;
-
- if(flags&SWS_PRINT_INFO)
- MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
- vo_format_name(srcFormat), vo_format_name(dstFormat));
- return c;
- }
-
- /* bgr16to32 */
- if((srcFormat==IMGFMT_BGR16 && dstFormat==IMGFMT_BGR32)
- ||(srcFormat==IMGFMT_RGB16 && dstFormat==IMGFMT_RGB32))
- {
- c->swScale= bgr16to32Wrapper;
+ c->swScale= yvu9toyv12Wrapper;
if(flags&SWS_PRINT_INFO)
MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
/* bgr24toYV12 */
if(srcFormat==IMGFMT_BGR24 && dstFormat==IMGFMT_YV12)
- {
c->swScale= bgr24toyv12Wrapper;
+
+ /* rgb/bgr -> rgb/bgr (no dither needed forms) */
+ if( (isBGR(srcFormat) || isRGB(srcFormat))
+ && (isBGR(dstFormat) || isRGB(dstFormat))
+ && !needsDither)
+ c->swScale= rgb2rgbWrapper;
+
+ /* LQ converters if -sws 0 or -sws 4*/
+ if(c->flags&(SWS_FAST_BILINEAR|SWS_POINT)){
+ /* rgb/bgr -> rgb/bgr (dither needed forms) */
+ if( (isBGR(srcFormat) || isRGB(srcFormat))
+ && (isBGR(dstFormat) || isRGB(dstFormat))
+ && needsDither)
+ c->swScale= rgb2rgbWrapper;
+ }
+ if(c->swScale){
if(flags&SWS_PRINT_INFO)
MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
vo_format_name(srcFormat), vo_format_name(dstFormat));
else
c->canMMX2BeUsed=0;
- getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
- getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
-
- // reuse chroma for 2 pixles rgb/bgr unless user wants full chroma interpolation
- if((isBGR(dstFormat) || isRGB(dstFormat)) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1;
-
- // drop eery 2. pixel for chroma calculation unless user wants full chroma
- if((isBGR(srcFormat) || isRGB(srcFormat) || srcFormat==IMGFMT_YUY2) && !(flags&SWS_FULL_CHR_V))
- c->chrSrcVSubSample=1;
-
- // drop eery 2. pixel for chroma calculation unless user wants full chroma
- if((isBGR(srcFormat) || isRGB(srcFormat)) && !(flags&SWS_FULL_CHR_H_INP))
- c->chrSrcHSubSample=1;
-
- c->chrIntHSubSample= c->chrDstHSubSample;
- c->chrIntVSubSample= c->chrSrcVSubSample;
-
- // note the -((-x)>>y) is so that we allways round toward +inf
- c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample);
- c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample);
- c->chrDstW= -((-dstW) >> c->chrDstHSubSample);
- c->chrDstH= -((-dstH) >> c->chrDstVSubSample);
-/* printf("%d %d %d %d / %d %d %d %d //\n",
- c->chrSrcW,
-c->chrSrcH,
-c->chrDstW,
-c->chrDstH,
-srcW,
-srcH,
-dstW,
-dstH);*/
c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW;
c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH;
const int filterAlign= cpuCaps.hasMMX ? 4 : 1;
initFilter(&c->hLumFilter, &c->hLumFilterPos, &c->hLumFilterSize, c->lumXInc,
- srcW , dstW, filterAlign, 1<<14, flags,
+ srcW , dstW, filterAlign, 1<<14,
+ (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags,
srcFilter->lumH, dstFilter->lumH);
initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc,
- (srcW+1)>>1, c->chrDstW, filterAlign, 1<<14, flags,
+ c->chrSrcW, c->chrDstW, filterAlign, 1<<14,
+ (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags,
srcFilter->chrH, dstFilter->chrH);
#ifdef ARCH_X86
/* precalculate vertical scaler filter coefficients */
initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize, c->lumYInc,
- srcH , dstH, 1, (1<<12)-4, flags,
+ srcH , dstH, 1, (1<<12)-4,
+ (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags,
srcFilter->lumV, dstFilter->lumV);
initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize, c->chrYInc,
- (srcH+1)>>1, c->chrDstH, 1, (1<<12)-4, flags,
- srcFilter->chrV, dstFilter->chrV);
+ c->chrSrcH, c->chrDstH, 1, (1<<12)-4,
+ (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags,
+ srcFilter->chrV, dstFilter->chrV);
// Calculate Buffer Sizes so that they wont run out while handling these damn slices
c->vLumBufSize= c->vLumFilterSize;
{
int chrI= i*c->chrDstH / dstH;
int nextSlice= MAX(c->vLumFilterPos[i ] + c->vLumFilterSize - 1,
- ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<1));
- nextSlice&= ~1; // Slices start at even boundaries
+ ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<c->chrSrcVSubSample));
+ nextSlice&= ~3; // Slices start at boundaries which are divisable through 4
if(c->vLumFilterPos[i ] + c->vLumBufSize < nextSlice)
c->vLumBufSize= nextSlice - c->vLumFilterPos[i ];
- if(c->vChrFilterPos[chrI] + c->vChrBufSize < (nextSlice>>1))
- c->vChrBufSize= (nextSlice>>1) - c->vChrFilterPos[chrI];
+ if(c->vChrFilterPos[chrI] + c->vChrBufSize < (nextSlice>>c->chrSrcVSubSample))
+ c->vChrBufSize= (nextSlice>>c->chrSrcVSubSample) - c->vChrFilterPos[chrI];
}
// allocate pixbufs (we use dynamic allocation because otherwise we would need to
MSG_INFO("\nSwScaler: Nearest Neighbor / POINT scaler, ");
else if(flags&SWS_AREA)
MSG_INFO("\nSwScaler: Area Averageing scaler, ");
+ else if(flags&SWS_BICUBLIN)
+ MSG_INFO("\nSwScaler: luma BICUBIC / chroma BILINEAR, ");
else
MSG_INFO("\nSwScaler: ehh flags invalid?! ");
c->lumMmx2FilterPos=NULL;
if(c->chrMmx2FilterPos) free(c->chrMmx2FilterPos);
c->chrMmx2FilterPos=NULL;
+ if(c->yuvTable) free(c->yuvTable);
+ c->yuvTable=NULL;
free(c);
}