📄 motest.c
字号:
bits = mbPartH * mbPartW; *pMse = mse; return bits;}/* * checkSubMbRectSize: * * Parameters: * current State of blocks of current MB * subMbMode Sub-macroblock mode (8x8, 4x8, 4x4) * mpX0 Sub-macroblock X index within MB * mpY0 Sub-macroblock Y index within MB * * Function: * Check whether motion vectors for the current sub-macroblock * conform to the AVC/H.264 standard's rect size restriction. * * Returns: * 1 for vectors ok, 0 for vectors not ok. */static int checkSubMbRectSize(blkState_s current[4][4], int subMbMode, int mpX0, int mpY0){ blkState_s (*curr)[BLK_PER_MB]; int minX, maxX, minY, maxY; int vecDiffX, vecDiffY; int rectSize; int i, j; curr = (blkState_s (*)[BLK_PER_MB])¤t[mpY0][mpX0]; switch (subMbMode) { case P_L0_8x4: vecDiffX = abs((curr[0][0].mv.x>>2) - (curr[1][0].mv.x>>2)); vecDiffY = abs((curr[0][0].mv.y>>2) - ((curr[1][0].mv.y>>2) + BLK_SIZE)); rectSize = (vecDiffX + 2*BLK_SIZE + 6) * (vecDiffY + BLK_SIZE + 6); break; case P_L0_4x8: vecDiffX = abs((curr[0][0].mv.x>>2) - ((curr[0][1].mv.x>>2) + BLK_SIZE)); vecDiffY = abs((curr[0][0].mv.y>>2) - (curr[0][1].mv.y>>2)); rectSize = (vecDiffX + BLK_SIZE + 6) * (vecDiffY + 2*BLK_SIZE + 6); break; case P_L0_4x4: minX = minY = 32767; maxX = maxY = -32768; for (j = 0; j < BLK_PER_MB/2; j++) { for (i = 0; i < BLK_PER_MB/2; i++) { minX = min(minX, curr[j][i].mv.x + i*BLK_SIZE*4); maxX = max(maxX, curr[j][i].mv.x + i*BLK_SIZE*4); minY = min(minY, curr[j][i].mv.y + j*BLK_SIZE*4); maxY = max(maxY, curr[j][i].mv.y + j*BLK_SIZE*4); } } vecDiffX = (maxX>>2) - (minX>>2); vecDiffY = (maxY>>2) - (minY>>2); rectSize = (vecDiffX + BLK_SIZE + 6) * (vecDiffY + BLK_SIZE + 6); break; default: return 1; } if (rectSize <= MAX_SUB_MB_RECT_SIZE) return 1; /* Rect size ok */ else return 0; /* Rect size too large */}/* * mesFindMotionFullSearch: * * Parameters: * pMb Macroblock information * pMeProf Parameters for controlling ME * refBufList Reference frame buffer array * nRefFrames Number of reference frames in the array * * Function: * Perform complexity scalable motion estimation based on the motion * estimation profile. * Here are how the blocks of different sizes are defined: * MB: Macroblock, no definition is needed * MB partition: One can have independent reference frame * Sub-MB: 8x8 MB partition * Sub-MB partition: parition within a sub-MB, sometime use MB parition * Block: 4x4 block, the smallest possible parition * * The motion vectors of all the modes are returned in "pMb->modeMvRef". * The actual decision is made in another function. * The best mode based on SAD after Hadamard has been found already in * this function. However, if RDO is enabled, the actual rate and * distortion will be calculated, the best mode could change. This is * performed in another function. * * Returns: * SAD of the best match. */int mesFindMotionFullSearch(macroblock_s *pMb, meProfile_s *pMeProf, refFrmBuf_s **refBufList, int nRefFrames){ int mode, r, i, j; int mpX0, mpX1, mpY0, mpY1; int shapeX, shapeY; int lambda; int blkMvBits; int mbSad, minMbSad; int mbPartSad, minMbPartSad, mbPartBits; u_int8 *refBlkPtrs[FRM_MAX_REF_FRAMES][16]; // maximally 5 frames u_int16 *refPartSum[FRM_MAX_REF_FRAMES]; mbPart_s mbPart; // one partition of MB or sub-MB LC3_s *plc3; pMeProf->pruneTreeTh = pMeProf->pruneThUnit * (pMb->qp - 12 - MIN_QP); // Is skipPredMv valid? Is it pointing within the extended search area? if (((pMeProf->area0[0] - pMb->idxX * MBK_SIZE) * 4 <= pMb->skipPredMv.x) && ((pMeProf->area0[1] - pMb->idxY * MBK_SIZE) * 4 <= pMb->skipPredMv.y) && ((pMeProf->area1[0] - (pMb->idxX + 1) * MBK_SIZE) * 4 >= pMb->skipPredMv.x) && ((pMeProf->area1[1] - (pMb->idxY + 1) * MBK_SIZE) * 4 >= pMb->skipPredMv.y)) { pMb->skipPredMvValid = 1; } else { pMb->skipPredMvValid = 0; } // need to initialize, 16x8, 8x16, 8x8, 8x4, 4x8 memset(& pMeProf->blkSADs[0][MOT_16x8][0], 32, sizeof(int16) * 5 * 16); ////////////////////////////////// LOW_COMPLEX_PROF3 plc3 = mbPart.plc3 = & (pMeProf->lc3); // : per mb init plc3->cnt++; plc3->do_qpel_mode_2_3 = plc3->do_qpel_mode_4=1; plc3->qp = (int16)pMb->qp; plc3->do_16x8 = 1; mbPart.refWidth = PrecomputeRefPointers(pMb, refBufList, nRefFrames, refBlkPtrs, refPartSum); lambda = pMb->lambda; mbPart.lambda = lambda; mbPart.lambdaCoarse = lambda; mbPart.profile = pMeProf->profile >> 4; minMbSad = INT_MAX; pMb->interModeFlags = pMeProf->interModeFlags; for (mode = MOT_16x16; mode <= MOT_8x8; mode ++) {///// LOW_COMPLEX_PROF3 // LC3_s *plc3 = mbPart.plc3; plc3->mode = (int16)mode;//////// // do not check MOT_8x8 only if modes above (include) MOT_8x8 are disabled if (((mode < MOT_8x8) && (pMb->interModeFlags & (1 << (mode - 1))) == 0) || ((mode == MOT_8x8) && (pMb->interModeFlags >> 3) == 0)) continue; if (mode == MOT_16x16) pMeProf->searchCtrFlag = CENTER_PRED_MV; else pMeProf->searchCtrFlag = CENTER_LARGER_BLOCK_MV; mbPart.mode = mode; shapeX = modePartWidth[mode]; // Width of mot. block in blocks shapeY = modePartHeight[mode]; // Height of mot. block in blocks mbPart.width = shapeX * BLK_SIZE; // Width of mot. block mbPart.height = shapeY * BLK_SIZE; // Height of mot. block // bits spent on coding mbType mbSad = lambda * uvlcBitsUnsigned[mode - 1]; for (mpY0 = 0; mpY0 < 4; mpY0 = mpY1) { mpY1 = mpY0 + shapeY; for (mpX0 = 0; mpX0 < 4; mpX0 = mpX1) { // best mode for this MB partition int bestMpMode; mpX1 = mpX0 + shapeX; bestMpMode = mode; minMbPartSad = INT_MAX; mbPartSad = 0; // just to avoid complaint // look for the best reference frame for this MB-parititon for (r = 0; r < nRefFrames; r ++) { blkState_s *bestMvRefPair; int refIdxBits; // set the search range mbPart.range = pMeProf->range[mode != MOT_16x16][r != 0]; // we may need to have only 1 vector for the partition bestMvRefPair = & pMb->current[mpY0][mpX0]; bestMvRefPair->ref = (int8) r; mbPartBits = 0; refIdxBits = vlcGetRefIndexBits(nRefFrames - 1, r); if (mode < MOT_8x8) { mbPart.x0 = mpX0; mbPart.x1 = mpX1; mbPart.y0 = mpY0; mbPart.y1 = mpY1; // the best vector will be filled in bestMvRefPair->mv mbPartSad = lambda * refIdxBits + mesBasicMode (pMb, pMeProf, & mbPart, refBlkPtrs[r], refPartSum[r], mode, & blkMvBits); if ((r == 0) && (mode == MOT_16x16)) { for (i = 0; i < 16; i ++) { pMeProf->searchCtrs[i][0] = bestMvRefPair->mv.x; pMeProf->searchCtrs[i][1] = bestMvRefPair->mv.y; } }#ifndef DISABLE_RDO // use a different cost function, if RDO is enabled if (((pMeProf->profile & 0x0F) == MODE_DECISION_RDO) && (nRefFrames > 1)) { int mse; mbPartBits = refIdxBits + blkMvBits + mesMbPartCost(pMb, refBlkPtrs[r], mbPart.refWidth, mpX0, mpY0, mpX1 - mpX0, mpY1 - mpY0, & mse); mbPartSad = mse + pMb->rdoLambda * mbPartBits; }#endif if (mbPartSad < minMbPartSad) { // This reference frame gives smaller SAD for this MB partition minMbPartSad = mbPartSad; for (j = mpY0; j < mpY1; j ++) for (i = mpX0; i < mpX1; i ++) pMb->modeMvRef[bestMpMode][j * 4 + i] = *bestMvRefPair; } } else { int subMbMode; // more modes under MOT_8x8, entire sub-MB must have same reference for (subMbMode = P_L0_8x8; subMbMode <= P_L0_4x4; subMbMode ++) { int blkW, blkH; if ((pMb->interModeFlags & (1 << (subMbMode + MOT_8x8 - 1))) == 0) continue; mbPartBits = refIdxBits + uvlcBitsUnsigned[subMbMode]; mbPartSad = lambda * mbPartBits; // Sub-MB partition width in 4x4 blocks blkW = modePartWidth[subMbMode + MOT_8x8]; // Sub-MB partition height in 4x4 blocks blkH = modePartHeight[subMbMode + MOT_8x8]; mbPart.width = blkW * BLK_SIZE; // Width of mot. block mbPart.height = blkH * BLK_SIZE; // Height of mot. block for (j = mpY0; j < mpY0 + 2; j += blkH) { mbPart.y0 = j; mbPart.y1 = j + blkH; for (i = mpX0; i < mpX0 + 2; i += blkW) { mbPart.x0 = i; mbPart.x1 = i + blkW; bestMvRefPair = & pMb->current[j][i]; bestMvRefPair->ref = (int8) r; mbPartSad += mesBasicMode(pMb, pMeProf, & mbPart, refBlkPtrs[r], refPartSum[r], subMbMode + MOT_8x8, & blkMvBits); mbPartBits += blkMvBits; // fill the vector for the remaining 4x4 blocks if (subMbMode == P_L0_4x8) bestMvRefPair[4] = bestMvRefPair[0]; else if (subMbMode <= P_L0_8x4) { bestMvRefPair[1] = bestMvRefPair[0]; if (subMbMode == P_L0_8x8) { bestMvRefPair[4] = bestMvRefPair[0]; bestMvRefPair[5] = bestMvRefPair[0]; } } } } if (pMeProf->pruneTreeFlag) { // save the motion vectors for sub-MB modes for (j = mpY0; j < mpY1; j ++) for (i = mpX0; i < mpX1; i ++) pMb->skipMVs[subMbMode][j * 4 + i] = pMb->current[j][i].mv; }#ifndef DISABLE_RDO // use a different cost function, if RDO is enabled if ((pMeProf->profile & 0x0F) == MODE_DECISION_RDO) { int mse; mbPartBits += mesMbPartCost(pMb, refBlkPtrs[r], mbPart.refWidth, mpX0, mpY0, 2, 2, & mse); mbPartSad = mse + pMb->rdoLambda * mbPartBits; }#endif // picks the best mode and best reference at the same time if (mbPartSad < minMbPartSad) { if (subMbMode == P_L0_8x8 || !pMeProf->subMbRectSizeFlag || checkSubMbRectSize(pMb->current, subMbMode, mpX0, mpY0)) { minMbPartSad = mbPartSad; // save the best mode pMb->interSubMbModes[mpY0 + (mpX0 >> 1)] = (u_int8) subMbMode; // both the motion vector and reference index are saved here for (j = mpY0; j < mpY1; j ++) for (i = mpX0; i < mpX1; i ++) pMb->modeMvRef[MOT_8x8][j * 4 + i] = pMb->current[j][i]; } } } // MOT_8x8, sub-MB mode search } // mode < MOT_8x8, or == MOT_8x8 } // reference frame // store best MVs in frame vector buffer for future prediction for (j = mpY0; j < mpY1; j ++) for (i = mpX0; i < mpX1; i ++) pMb->current[j][i] = pMb->modeMvRef[bestMpMode][j * 4 + i]; mbSad += minMbPartSad; } // MB partition X } // MB partition Y // if 4 sub-MB all refer to reference frame 0, cost can be reduced if ((nRefFrames > 1) && (mode == MOT_8x8)) { if ((pMb->current[0][0].ref == 0) && (pMb->current[0][2].ref == 0) && (pMb->current[2][0].ref == 0) && (pMb->current[2][2].ref == 0)) { // 1 bit has been used unnecessarily for signaling reference indices mbSad -= lambda * 4; } } // find the best mode if (mbSad < minMbSad) { minMbSad = mbSad; pMb->interMode = mode; } if ((pMeProf->pruneTreeFlag) && (mode == MOT_16x16) && (minMbSad < 16 * pMeProf->pruneTreeTh)) { pMb->interModeFlags = 1 << (MOT_16x16 - 1); break; } } // mode return minMbSad;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -