📄 swscale.c
字号:
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[], stride_t srcStride[], int srcSliceY,
int srcSliceH, uint8_t* dst[], stride_t dstStride[]){
if(isPacked(c->srcFormat))
{
if(dstStride[0]==srcStride[0] && srcStride[0] > 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] && srcStride[plane] > 0)
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_YVYU:
case IMGFMT_VYUY:
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 COMPILE_ALTIVEC
if (c->flags & SWS_CPU_CAPS_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;
}
// Be carefull when you modify SwsContext after returning from sws_getContext.
// SwsContext is copied to array for multithreading.
// sws_scale_ordered modify c->sliceDir. It does not matter for now.
SwsContext *sws_getContext(int srcW, int srcH, int origSrcFormat, int dstW, int dstH, int origDstFormat, SwsParams *params,
SwsFilter *srcFilter, SwsFilter *dstFilter){
return sws_getContextEx(srcW, srcH, origSrcFormat, dstW, dstH, origDstFormat, params,
srcFilter, dstFilter, GetCPUCount());
}
SwsContext *sws_getContextEx(int srcW, int srcH, int origSrcFormat, int dstW, int dstH, int origDstFormat, SwsParams *params,
SwsFilter *srcFilter, SwsFilter *dstFilter, int threadCount){
SwsContext *c;
int i;
int usesVFilter, usesHFilter;
int unscaled, needsDither;
int srcFormat, dstFormat;
SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};
#if defined(ARCH_X86) || defined(ARCH_X86_64)
if(params->cpu & SWS_CPU_CAPS_MMX)
asm volatile("emms\n\t"::: "memory");
#else
params->cpu=0;
#endif
#ifndef RUNTIME_CPUDETECT //ensure that the flags match the compiled variant if cpudetect is off
flags &= ~(SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2|SWS_CPU_CAPS_3DNOW|SWS_CPU_CAPS_ALTIVEC);
#ifdef HAVE_MMX2
flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2;
#elif defined (HAVE_3DNOW)
flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_3DNOW;
#elif defined (HAVE_MMX)
flags |= SWS_CPU_CAPS_MMX;
#elif defined (HAVE_ALTIVEC)
flags |= SWS_CPU_CAPS_ALTIVEC;
#endif
#endif /* RUNTIME_CPUDETECT */
if(clip_table[512] != 255) globalInit();
if(rgb15to16 == NULL) sws_rgb2rgb_init(params);
/* avoid duplicate Formats, so we don't need to check to much */
srcFormat = remove_dup_fourcc(origSrcFormat);
dstFormat = remove_dup_fourcc(origDstFormat);
unscaled = (srcW == dstW && srcH == dstH);
needsDither= (isBGR(dstFormat) || isRGB(dstFormat))
&& (dstFormat&0xFF)<24
&& ((dstFormat&0xFF)<(srcFormat&0xFF) || (!(isRGB(srcFormat) || isBGR(srcFormat))));
if(!isSupportedIn(srcFormat))
{
MSG_ERR("swScaler: %s is not supported as input format\n", sws_format_name(srcFormat));
return NULL;
}
if(!isSupportedOut(dstFormat))
{
MSG_ERR("swScaler: %s is not supported as output format\n", sws_format_name(dstFormat));
return NULL;
}
/* sanity check */
if(srcW<4 || srcH<1 || dstW<8 || dstH<1) //FIXME check if these are enough and try to lowwer them after fixing the relevant parts of the code
{
MSG_ERR("swScaler: %dx%d -> %dx%d is invalid scaling dimension\n",
srcW, srcH, dstW, dstH);
return NULL;
}
if(!dstFilter) dstFilter= &dummyFilter;
if(!srcFilter) srcFilter= &dummyFilter;
c= av_malloc(sizeof(SwsContext)*threadCount); // array support up to c[threadCount-1]. "c->" is identical to "c[0]."
memset(c, 0, sizeof(SwsContext));
c->srcW= srcW;
c->srcH= srcH;
c->dstW= dstW;
c->dstH= dstH;
c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW;
c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH;
c->params= *params;
c->dstFormat= dstFormat;
c->srcFormat= srcFormat;
c->origDstFormat= origDstFormat;
c->origSrcFormat= origSrcFormat;
c->vRounder= 4* 0x0001000100010001ULL;
usesHFilter= usesVFilter= 0;
if(dstFilter->lumV!=NULL && dstFilter->lumV->length>1) usesVFilter=1;
if(dstFilter->lumH!=NULL && dstFilter->lumH->length>1) usesHFilter=1;
if(dstFilter->chrV!=NULL && dstFilter->chrV->length>1) usesVFilter=1;
if(dstFilter->chrH!=NULL && dstFilter->chrH->length>1) usesHFilter=1;
if(srcFilter->lumV!=NULL && srcFilter->lumV->length>1) usesVFilter=1;
if(srcFilter->lumH!=NULL && srcFilter->lumH->length>1) usesHFilter=1;
if(srcFilter->chrV!=NULL && srcFilter->chrV->length>1) usesVFilter=1;
if(srcFilter->chrH!=NULL && srcFilter->chrH->length>1) usesHFilter=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)) && !(params->subsampling&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1;
// drop some chroma lines if the user wants it
c->vChrDrop= params->v_chr_drop;// (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)) && !(params->subsampling&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);
sws_setColorspaceDetails(c, Inverse_Table_6_9[SWS_CS_DEFAULT], 0, Inverse_Table_6_9[SWS_CS_DEFAULT] /* FIXME*/, 0, 0, 1<<16, 1<<16);
/* unscaled special Cases */
if(unscaled && !usesHFilter && !usesVFilter)
{
/* yv12_to_nv12 */
if(srcFormat == IMGFMT_YV12 && (dstFormat == IMGFMT_NV12 || dstFormat == IMGFMT_NV21))
{
c->swScale= PlanarToNV12Wrapper;
}
if((srcFormat == IMGFMT_NV12 || srcFormat == IMGFMT_NV21) && dstFormat == IMGFMT_YV12)
{
c->swScale= NV12ToPlanarWrapper;
}
/* yuv2bgr */
if((srcFormat==IMGFMT_YV12 || srcFormat==IMGFMT_422P) && (isBGR(dstFormat) || isRGB(dstFormat)))
{
c->swScale= yuv2rgb_get_func_ptr(c);
}
if( srcFormat==IMGFMT_YVU9 && dstFormat==IMGFMT_YV12 )
{
c->swScale= yvu9toyv12Wrapper;
}
/* 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->params.methodLuma.method&(SWS_FAST_BILINEAR|SWS_POINT) && c->params.methodChroma.method&(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;
/* yv12_to_yuy2 */
if(srcFormat == IMGFMT_YV12 &&
(dstFormat == IMGFMT_YUY2 || dstFormat == IMGFMT_UYVY || dstFormat == IMGFMT_YVYU || dstFormat== IMGFMT_VYUY))
{
if (dstFormat == IMGFMT_YUY2)
c->swScale= PlanarToYuy2Wrapper;
else if (dstFormat == IMGFMT_UYVY)
c->swScale= PlanarToUyvyWrapper;
else if (dstFormat == IMGFMT_VYUY)
c->swScale= PlanarToVyuyWrapper;
else
c->swScale= PlanarToYvyuWrapper;
}
}
#ifdef COMPILE_ALTIVEC
if ((c->flags & SWS_CPU_CAPS_ALTIVEC) &&
((srcFormat == IMGFMT_YV12 &&
(dstFormat == IMGFMT_YUY2 || dstFormat == IMGFMT_UYVY)))) {
// unscaled YV12 -> packed YUV, we want speed
if (dstFormat == IMGFMT_YUY2)
c->swScale= yv12toyuy2_unscaled_altivec;
else
c->swScale= yv12touyvy_unscaled_altivec;
}
#endif
/* simple copy */
if( srcFormat == dstFormat
|| (isPlanarYUV(srcFormat) && isGray(dstFormat))
|| (isPlanarYUV(dstFormat) && isGray(srcFormat))
)
{
c->swScale= simpleCopy;
}
if(c->swScale){
if(params->debug&SWS_PRINT_INFO)
MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n",
sws_format_name(srcFormat), sws_format_name(dstFormat));
return c;
}
}
if(params->cpu & SWS_CPU_CAPS_MMX2)
{
c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0;
if(!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (params->methodLuma.method&SWS_FAST_BILINEAR))
{
if(params->debug&SWS_PRINT_INFO)
MSG_INFO("SwScaler: output Width is not a multiple of 32 -> no MMX2 scaler\n");
}
if(usesHFilter) c->canMMX2BeUsed=0;
}
else
c->canMMX2BeUsed=0;
c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW;
c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH;
// match pixel 0 of the src to pix
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -