+static int 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]);
+ return srcSliceH;
+}
+
+static int yvu9toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+ 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++)
+ {
+ memcpy(dstPtr, srcPtr, c->srcW);
+ srcPtr+= srcStride[0];
+ dstPtr+= dstStride[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]);
+ }
+ return srcSliceH;
+}
+
+/**
+ * bring pointers in YUV order instead of YVU
+ */
+static inline void sws_orderYUV(int format, uint8_t * sortedP[], int sortedStride[], uint8_t * p[], int stride[]){
+ if(format == IMGFMT_YV12 || format == IMGFMT_YVU9
+ || format == IMGFMT_444P || format == IMGFMT_422P || format == IMGFMT_411P){
+ sortedP[0]= p[0];
+ sortedP[1]= p[2];
+ sortedP[2]= p[1];
+ sortedStride[0]= stride[0];
+ sortedStride[1]= stride[2];
+ sortedStride[2]= stride[1];
+ }
+ else if(isPacked(format) || isGray(format) || format == IMGFMT_Y8)
+ {
+ sortedP[0]= p[0];
+ sortedP[1]=
+ sortedP[2]= NULL;
+ sortedStride[0]= stride[0];
+ sortedStride[1]=
+ sortedStride[2]= 0;
+ }
+ else if(format == IMGFMT_I420 || format == IMGFMT_IYUV)
+ {
+ sortedP[0]= p[0];
+ sortedP[1]= p[1];
+ sortedP[2]= p[2];
+ sortedStride[0]= stride[0];
+ sortedStride[1]= stride[1];
+ sortedStride[2]= stride[2];
+ }
+ else if(format == IMGFMT_NV12 || format == IMGFMT_NV21)
+ {
+ sortedP[0]= p[0];
+ sortedP[1]= p[1];
+ sortedP[2]= NULL;
+ sortedStride[0]= stride[0];
+ sortedStride[1]= stride[1];
+ sortedStride[2]= 0;
+ }else{
+ MSG_ERR("internal error in orderYUV\n");
+ }
+}
+
+/* unscaled copy like stuff (assumes nearly identical formats) */
+static int simpleCopy(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+ int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+ if(isPacked(c->srcFormat))
+ {
+ if(dstStride[0]==srcStride[0])
+ memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
+ else
+ {
+ int i;
+ uint8_t *srcPtr= src[0];
+ uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
+ int length=0;
+
+ /* universal length finder */
+ while(length+c->srcW <= ABS(dstStride[0])
+ && length+c->srcW <= ABS(srcStride[0])) length+= c->srcW;
+ ASSERT(length!=0);
+
+ for(i=0; i<srcSliceH; i++)
+ {
+ memcpy(dstPtr, srcPtr, length);
+ srcPtr+= srcStride[0];
+ dstPtr+= dstStride[0];
+ }
+ }
+ }
+ else
+ { /* Planar YUV or gray */
+ int plane;
+ for(plane=0; plane<3; plane++)
+ {
+ 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], 128, dstStride[plane]*height);
+ }
+ else
+ {
+ if(dstStride[plane]==srcStride[plane])
+ memcpy(dst[plane] + dstStride[plane]*y, src[plane], height*dstStride[plane]);
+ else
+ {
+ int i;
+ uint8_t *srcPtr= src[plane];
+ uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
+ for(i=0; i<height; i++)
+ {
+ memcpy(dstPtr, srcPtr, length);
+ srcPtr+= srcStride[plane];
+ dstPtr+= dstStride[plane];
+ }
+ }
+ }
+ }
+ }
+ return srcSliceH;
+}
+
+static int remove_dup_fourcc(int fourcc)
+{
+ switch(fourcc)
+ {
+ case IMGFMT_I420:
+ case IMGFMT_IYUV: return IMGFMT_YV12;
+ case IMGFMT_Y8 : return IMGFMT_Y800;
+ case IMGFMT_IF09: return IMGFMT_YVU9;
+ default: return fourcc;
+ }
+}
+
+static void getSubSampleFactors(int *h, int *v, int format){
+ switch(format){
+ case IMGFMT_UYVY:
+ case IMGFMT_YUY2:
+ *h=1;
+ *v=0;
+ break;
+ case IMGFMT_YV12:
+ case IMGFMT_Y800: //FIXME remove after different subsamplings are fully implemented
+ case IMGFMT_NV12:
+ case IMGFMT_NV21:
+ *h=1;
+ *v=1;
+ break;
+ case IMGFMT_YVU9:
+ *h=2;
+ *v=2;
+ break;
+ case IMGFMT_444P:
+ *h=0;
+ *v=0;
+ break;
+ case IMGFMT_422P:
+ *h=1;
+ *v=0;
+ break;
+ case IMGFMT_411P:
+ *h=2;
+ *v=0;
+ break;
+ default:
+ *h=0;
+ *v=0;
+ break;
+ }
+}
+
+static uint16_t roundToInt16(int64_t f){
+ int r= (f + (1<<15))>>16;
+ if(r<-0x7FFF) return 0x8000;
+ else if(r> 0x7FFF) return 0x7FFF;
+ else return r;
+}
+
+/**
+ * @param inv_table the yuv2rgb coeffs, normally Inverse_Table_6_9[x]
+ * @param fullRange if 1 then the luma range is 0..255 if 0 its 16..235
+ * @return -1 if not supported
+ */
+int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation){
+ int64_t crv = inv_table[0];
+ int64_t cbu = inv_table[1];
+ int64_t cgu = -inv_table[2];
+ int64_t cgv = -inv_table[3];
+ int64_t cy = 1<<16;
+ int64_t oy = 0;
+
+ if(isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1;
+ memcpy(c->srcColorspaceTable, inv_table, sizeof(int)*4);
+ memcpy(c->dstColorspaceTable, table, sizeof(int)*4);
+
+ c->brightness= brightness;
+ c->contrast = contrast;
+ c->saturation= saturation;
+ c->srcRange = srcRange;
+ c->dstRange = dstRange;
+
+ c->uOffset= 0x0400040004000400LL;
+ c->vOffset= 0x0400040004000400LL;
+
+ if(!srcRange){
+ cy= (cy*255) / 219;
+ oy= 16<<16;
+ }
+
+ cy = (cy *contrast )>>16;
+ crv= (crv*contrast * saturation)>>32;
+ cbu= (cbu*contrast * saturation)>>32;
+ cgu= (cgu*contrast * saturation)>>32;
+ cgv= (cgv*contrast * saturation)>>32;
+
+ oy -= 256*brightness;
+
+ c->yCoeff= roundToInt16(cy *8192) * 0x0001000100010001ULL;
+ c->vrCoeff= roundToInt16(crv*8192) * 0x0001000100010001ULL;
+ c->ubCoeff= roundToInt16(cbu*8192) * 0x0001000100010001ULL;
+ c->vgCoeff= roundToInt16(cgv*8192) * 0x0001000100010001ULL;
+ c->ugCoeff= roundToInt16(cgu*8192) * 0x0001000100010001ULL;
+ c->yOffset= roundToInt16(oy * 8) * 0x0001000100010001ULL;
+
+ yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation);
+ //FIXME factorize
+
+#ifdef HAVE_ALTIVEC
+ yuv2rgb_altivec_init_tables (c, inv_table, brightness, contrast, saturation);
+#endif
+ return 0;
+}
+
+/**
+ * @return -1 if not supported
+ */
+int sws_getColorspaceDetails(SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, int *brightness, int *contrast, int *saturation){
+ if(isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1;
+
+ *inv_table = c->srcColorspaceTable;
+ *table = c->dstColorspaceTable;
+ *srcRange = c->srcRange;
+ *dstRange = c->dstRange;
+ *brightness= c->brightness;
+ *contrast = c->contrast;
+ *saturation= c->saturation;
+
+ return 0;
+}
+
+SwsContext *sws_getContext(int srcW, int srcH, int origSrcFormat, int dstW, int dstH, int origDstFormat, int flags,
+ SwsFilter *srcFilter, SwsFilter *dstFilter, double *param){