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

📄 motioncompute.c

📁 DM642的mpeg4编码
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (bDirection & 1) 
		{
			CheckMember(x - SearchSize, y, pData, 1);
		}
		if (bDirection & 2) 
		{
	    	CheckMember(x + SearchSize, y, pData, 2);
		}
		if (bDirection & 4)
		{
			CheckMember(x, y - SearchSize, pData, 4);
		}
		if (bDirection & 8) 
		{
			CheckMember(x, y + SearchSize, pData, 8);
		}

		if (*iDirection == 0)
		{
			break;
		}		
	
		bDirection = *iDirection;
		x = pData->CurrentMv->x; y = pData->CurrentMv->y;
		if (bDirection & 3) 
		{	
			CheckMember(x, y + SearchSize, pData, 8);
			CheckMember(x, y - SearchSize, pData, 4);
		}
		else 
		{		
			CheckMember(x + SearchSize, y, pData, 2);
			CheckMember(x - SearchSize, y, pData, 1);
		}
		bDirection |= *iDirection;
		x = pData->CurrentMv->x; y = pData->CurrentMv->y;
	}
}

void DiaSearch2(int x, int y, MvSearchData* pData, short bDirection, CheckFunc* CheckMember)
{
	unsigned int* const iDirection = &pData->dir;

	for(;;) 
	{ 
		*iDirection = 0;
		if (bDirection & 1)
		{
			CheckMember(x - SearchSize, y, pData, 1);
		}
		if (bDirection & 2) 
		{
			CheckMember(x + SearchSize, y, pData, 2);
		}
		if (bDirection & 4) 
		{
			CheckMember(x, y - SearchSize, pData, 4);
		}
		if (bDirection & 8) 
		{
			CheckMember(x, y + SearchSize, pData, 8);
		}

		if (*iDirection)
		{
			bDirection = *iDirection;
			*iDirection = 0;
			x = pData->CurrentMv->x; y = pData->CurrentMv->y;
			if (bDirection & 3)
			{	
				CheckMember(x, y + SearchSize, pData, 8);
				CheckMember(x, y - SearchSize, pData, 4);
			} 
			else 
			{	
				CheckMember(x + SearchSize, y, pData, 2);
				CheckMember(x - SearchSize, y, pData, 1);
			}

			if (*iDirection) 
			{
				bDirection += *iDirection;
				x = pData->CurrentMv->x; y = pData->CurrentMv->y;
			}
		} 
		else
		{		
			switch (bDirection) 
			{
			case 2:
				CheckMember(x + SearchSize, y - SearchSize, pData, 2 + 4);
				CheckMember(x + SearchSize, y + SearchSize, pData, 2 + 8);
				break;
			case 1:
				CheckMember(x - SearchSize, y - SearchSize, pData, 1 + 4);
				CheckMember(x - SearchSize, y + SearchSize, pData, 1 + 8);
				break;
			case 2 + 4:
				CheckMember(x - SearchSize, y - SearchSize, pData, 1 + 4);
				CheckMember(x + SearchSize, y - SearchSize, pData, 2 + 4);
				CheckMember(x + SearchSize, y + SearchSize, pData, 2 + 8);
				break;
			case 4:
				CheckMember(x + SearchSize, y - SearchSize, pData, 2 + 4);
				CheckMember(x - SearchSize, y - SearchSize, pData, 1 + 4);
				break;
			case 8:
				CheckMember(x + SearchSize, y + SearchSize, pData, 2 + 8);
				CheckMember(x - SearchSize, y + SearchSize, pData, 1 + 8);
				break;
			case 1 + 4:
				CheckMember(x - SearchSize, y + SearchSize, pData, 1 + 8);
				CheckMember(x - SearchSize, y - SearchSize, pData, 1 + 4);
				CheckMember(x + SearchSize, y - SearchSize, pData, 2 + 4);
				break;
			case 2 + 8:
				CheckMember(x + SearchSize, y - SearchSize, pData, 2 + 4);
				CheckMember(x + SearchSize, y + SearchSize, pData, 2 + 8);
				CheckMember(x - SearchSize, y + SearchSize, pData, 1 + 8);
				break;
			case 1 + 8:
				CheckMember(x - SearchSize, y - SearchSize, pData, 1 + 4);
				CheckMember(x - SearchSize, y + SearchSize, pData, 1 + 8);
				CheckMember(x + SearchSize, y + SearchSize, pData, 2 + 8);
				break;
			default:		
				CheckMember(x - SearchSize, y - SearchSize, pData, 1 + 4);
				CheckMember(x - SearchSize, y + SearchSize, pData, 1 + 8);
				CheckMember(x + SearchSize, y - SearchSize, pData, 2 + 4);
				CheckMember(x + SearchSize, y + SearchSize, pData, 2 + 8);
				break;
			}
			if (!*iDirection) 
			{
				break;	
			}
			bDirection = *iDirection;
			x = pData->CurrentMv->x; y = pData->CurrentMv->y;
		}
	}
}

void SubpixelSearch(VECTOR centerMV, MvSearchData* pData, short dir, CheckFunc* CheckMember)
{
    
	CheckMember(centerMV.x, centerMV.y - 1, pData, dir);
	CheckMember(centerMV.x + 1, centerMV.y - 1, pData, dir);
	CheckMember(centerMV.x + 1, centerMV.y, pData, dir);
	CheckMember(centerMV.x + 1, centerMV.y + 1, pData, dir);
	CheckMember(centerMV.x, centerMV.y + 1, pData, dir);
	CheckMember(centerMV.x - 1, centerMV.y + 1, pData, dir);
	CheckMember(centerMV.x - 1, centerMV.y, pData, dir);
	CheckMember(centerMV.x - 1, centerMV.y - 1, pData, dir);
}

void SearchBlock(MvSearchData* pOldData,
				 int x, int y,
				 short  iMBWidth,
				 short  iWidth, short iHeight,
				 MacroBlock* pCurMB,
				 MacroBlock* Mbs,
				 short block,
				 MvSearchData* pData)
{
	int i = 0;

	*pData->iMinSad = *(pOldData->iMinSad + 1 + block);
	*pData->CurrentMv = *(pOldData->CurrentMv + 1 + block);

	pData->PredMV = Get_pmv(Mbs, iMBWidth, 0, x/2, y/2, block);
	if (block != 0)	
	{
		i = ComputeMvBits(pData->CurrentMv->x, pData->CurrentMv->y, pData->PredMV, pData->iFcode);
	}

	*(pData->iMinSad) += (pData->fourmvbit * i);


	pData->RefP[0] = pOldData->RefP[0] + 8 * ((block&1) + pData->iExtWidth*(block>>1));
	pData->RefP[1] = pOldData->RefP[1] + 8 * ((block&1) + pData->iExtWidth*(block>>1));
	pData->RefP[2] = pOldData->RefP[2] + 8 * ((block&1) + pData->iExtWidth*(block>>1));
	pData->RefP[3] = pOldData->RefP[3] + 8 * ((block&1) + pData->iExtWidth*(block>>1));

	pData->CurY = pOldData->CurY + 8 * ((block&1) + pData->iExtWidth*(block>>1));

	GetMvSearchRange(pData, x, y, 3, iWidth, iHeight, pData->iFcode);

	DiaSearch2(pData->CurrentMv->x, pData->CurrentMv->y, pData, 255, CheckMemberBlock);
#ifdef HALF_PIXEL	
	SubpixelSearch(pData->CurrentMv[0], pData, 0, CheckMemberBlock);
#endif
	
	pCurMB->PredMv[block].x = pData->CurrentMv->x - pData->PredMV.x;
	pCurMB->PredMv[block].y = pData->CurrentMv->y - pData->PredMV.y;	

	*(pOldData->iMinSad + 1 + block) = *pData->iMinSad;
	*(pOldData->CurrentMv + 1 + block) = *pData->CurrentMv;

	pCurMB->Mv[block] = *pData->CurrentMv;
	pCurMB->LumBlockSad[block] = 4 *(*pData->iMinSad);
}

int SkipModeDecision(const Image8 * Current, const Image8 * Reference,
					 const int x, const int y,
					 const short iStride, const unsigned int iQuant)
{
	int offset = x*8;
	unsigned int sadC = ComputBlockSad(Current->Cb + offset, Reference->Cb + offset, iStride);

	if (sadC > iQuant * ChroSkip)
	{
	   return 0;
	}

	sadC += ComputBlockSad(Current->Cr + offset, Reference->Cr + offset, iStride);

	if (sadC > iQuant * ChroSkip) 
	{
		return 0;
	}

	return 1;
}
//***********************************************************************************************
//函 数 名:GetMBParameter()
//函数功能:得到当前宏块的运动矢量
//形式参数:pEncoder  编码器指针
//	        pRefImage, pRefImageH, pRefImageV pRefImageHV  参考图像
//		    pCurMB   当前宏块
//			pData  运动估计参数结构体
//			x,y    宏块标号
//返 回 值:void
//***********************************************************************************************
void GetMBParameter(Encoder* pEncoder,
					Image8* pCurImage,
				    Image8* pRefImage,
				    MacroBlock* pCurMB, 
				    MvSearchData* pData, 
				    short x, 
				    short y)
{
    short iTempBits;

	short iThresh;

	int bSAD;

	short i;

	VECTOR startMV, backupMV;

	int Inter4vFlag = 1;
		
	int sumx = 0, sumy = 0;

	/* K = 4 */
	const unsigned int TabK4[16] =
	{ 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };


    short iMBWidth = pEncoder->pCurFrameInfo->vop_width>>4;
	short iMBHeight = pEncoder->pCurFrameInfo->vop_height>>4;

	short iWidth = pEncoder->pCurFrameInfo->vop_width;
	short iHeight = pEncoder->pCurFrameInfo->vop_height;


	MacroBlock* Mbs = &pEncoder->pCurFrameInfo->pMB[0];
	MacroBlock* pRefMbs = &pEncoder->pForFrameInfo->pMB[0];

	VECTOR PredictMv[7];

	pData->chromaX = pData->chromaY = 0; 

	//获取搜索范围
    //  get mv range
	GetMvSearchRange(pData, x, y, 4, pEncoder->pCurFrameInfo->vop_width, pEncoder->pCurFrameInfo->vop_height, pData->iFcode);
   
	//获得预测的运动向量
    GetPredictMv(Mbs, iMBWidth, x, y, PredictMv, pData->LumTempBlockSad);

	//将当前宏块的数据Y/U/V的首地址给pData的相应的量
    pData->CurY = pCurImage->Y + x* 16;
	pData->CurU = pCurImage->Cb + x*8;
	pData->CurV = pCurImage->Cr + x*8;
	
	//将差值后的当前宏块的值给pData->RefP
	pData->RefP[0] = pRefImage->Y + x* 16;

	pData->RefP[4] = pRefImage->Cb + x*8;
	pData->RefP[5] = pRefImage->Cr + x*8;

    pData->dir = 0;
	pData->onemvbit = VectorMacroBlock[pCurMB->quant];
	pData->fourmvbit =  VectorBlock[pCurMB->quant];

    memset(pData->CurrentMv, 0, sizeof(VECTOR)*5);
 
	pData->PredMV = PredictMv[0];
	//计算运动矢量编码比特
    iTempBits = ComputeMvBits(0,0, pData->PredMV, pData->iFcode);

	pData->iMinSad[0] = pCurMB->LumMBlockSad + pData->onemvbit * iTempBits;
	pData->iMinSad[1] = pCurMB->LumBlockSad[0] + pData->fourmvbit * iTempBits;
    pData->iMinSad[2] = pCurMB->LumBlockSad[1];
	pData->iMinSad[3] = pCurMB->LumBlockSad[2];
	pData->iMinSad[4] = pCurMB->LumBlockSad[3];
//  如果不采用率失真决策模型,并且不是当前帧的第一宏块,那么使用一种方法设置阀值threshA,否则阀值threshA为512。
	if  (x | y) 
	{
		iThresh = pData->LumTempBlockSad[0]; 

		if (iThresh < 512) 
		{
		   iThresh = 512;
		}
		else if (iThresh > 1024)
		{
			iThresh = 1024;
		}
	} 
	else
	{
		iThresh = 512;
	}
   
	//对pmv作进一步的设置,做运算前的准备
	MEPre(PredictMv, x, y, iMBWidth, iMBHeight,  pRefMbs + x + y * iMBWidth);
	
	//逐一检查mpv[1-6]这六个最可能运动向量,如果发现他们与以前的运动不同,就调用CheckMemberMB做运动估计
    for (i = 1; i < 7; i++)
	{
        if (!VectorCheck(PredictMv, i))
		{
			CheckMemberMB(PredictMv[i].x, PredictMv[i].y, pData, i);
			if (pData->iMinSad[0] <= iThresh)
			{ 
			   i++;
			   break;
			}
		}
	}

//判断是否进行inter4v的搜索
	if ((pData->iMinSad[0] <= iThresh) || 
		(MVequal(pData->CurrentMv[0], (pRefMbs+x+y*iMBWidth)->Mv[0]) &&
		(pData->iMinSad[0] < (pRefMbs+x+y*iMBWidth)->LumMBlockSad)))
	{
		Inter4vFlag = 0;
	}
	//inter4v的搜索
	else 
	{
		short mask = GetMask(PredictMv, i, pData->dir); 
		DiaSearch2(pData->CurrentMv->x, pData->CurrentMv->y, pData, mask, CheckMemberMB);
	

		startMV = pData->PredMV;
		backupMV = pData->CurrentMv[0];

		if (!(MVequal(startMV, backupMV))) 
		{
			bSAD = pData->iMinSad[0]; 
			pData->iMinSad[0] = ErrorOfMv;
			//以宏块为单位搜索
			CheckMemberMB(startMV.x, startMV.y, pData, 255);
			//
			DiaSearch1(startMV.x, startMV.y, pData, 255, CheckMemberMB);

			if (bSAD < pData->iMinSad[0]) 
			{
				pData->CurrentMv[0] = backupMV;
				pData->iMinSad[0] = bSAD; 
			}
		}

		/*
		backupMV = pData->CurrentMv[0];
		startMV.x = startMV.y = 1;

		if (!(MVequal(startMV, backupMV)))
		{
			bSAD = pData->iMinSad[0]; 
			pData->iMinSad[0] = ErrorOfMv;

			CheckMemberMB(startMV.x, startMV.y, pData, 255);
			DiaSearch1(startMV.x, startMV.y, pData, 255, CheckMemberMB);

			if (bSAD < pData->iMinSad[0]) 
			{
				pData->CurrentMv[0] = backupMV;
				pData->iMinSad[0] = bSAD;
			}
		}
		*/
	}
#ifdef HALF_PIXEL
	SubpixelSearch(pData->CurrentMv[0], pData, 0, CheckMemberMB);	
#endif
    if (pData->iMinSad[0] < (int)pCurMB->quant * 30)
	{
		Inter4vFlag = 0;
	}

	if (Inter4vFlag)
	{
		MvSearchData pData8;
		memcpy(&pData8, pData, sizeof(MvSearchData)); 

		SearchBlock(pData, 2*x, 2*y, iMBWidth, iWidth, iHeight, pCurMB, Mbs, 0, &pData8);
		SearchBlock(pData, 2*x + 1, 2*y, iMBWidth, iWidth, iHeight, pCurMB, Mbs, 1, &pData8);
		SearchBlock(pData, 2*x, 2*y + 1, iMBWidth, iWidth, iHeight, pCurMB, Mbs, 2, &pData8);
		SearchBlock(pData, 2*x + 1, 2*y + 1, iMBWidth, iWidth, iHeight, pCurMB, Mbs, 3, &pData8);
		
		for (i = 1; i < 5; i++) 
		{
			sumx += pData->CurrentMv[i].x;
			sumy += pData->CurrentMv[i].y;
		}
	
		pData->iMinSad[1] += ComputeChromaSAD((sumx >> 3) + TabK4[sumx & 0xf],
											(sumy >> 3) + TabK4[sumy & 0xf], pData);
		
	}
	else 
	{
		pData->iMinSad[1] = ErrorOfMv;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -