📄 motioncompute.c
字号:
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 + -