⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swscale.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -