📄 motest.c
字号:
for (m = MOT_16x8; m <= MOT_4x8; m ++) { sadsPtr += 16; partSad = sadsPtr[0]; if (sadsPtr[0] < bestSad) { bestSad = partSad; *bestLazyMode = m; } } break; case MOT_4x8: bestSad = sadsPtr[0] + sadsPtr[4]; for (m = MOT_16x8; m <= MOT_8x8; m ++) { sadsPtr += 16; partSad = sadsPtr[0] + sadsPtr[4]; if (partSad < bestSad) { bestSad = partSad; *bestLazyMode = m; } } break; case MOT_8x4: bestSad = sadsPtr[0] + sadsPtr[1]; for (m = MOT_16x8; m <= MOT_8x8; m ++) { sadsPtr += 16; partSad = sadsPtr[0] + sadsPtr[1]; if (partSad < bestSad) { bestSad = partSad; *bestLazyMode = m; } } break; case MOT_8x8: bestSad = sadsPtr[0] + sadsPtr[1] + sadsPtr[4] + sadsPtr[5]; for (m = MOT_16x8; m <= MOT_8x16; m ++) { sadsPtr += 16; partSad = sadsPtr[0] + sadsPtr[1] + sadsPtr[4] + sadsPtr[5]; if (partSad < bestSad) { bestSad = partSad; *bestLazyMode = m; } } break; case MOT_8x16: bestSad = sadsPtr[0] + sadsPtr[1] + sadsPtr[4] + sadsPtr[5]; bestSad += sadsPtr[8] + sadsPtr[9] + sadsPtr[12] + sadsPtr[13]; break; case MOT_16x8: bestSad = sadsPtr[0] + sadsPtr[1] + sadsPtr[2] + sadsPtr[3]; bestSad += sadsPtr[4] + sadsPtr[5] + sadsPtr[6] + sadsPtr[7]; break; } return bestSad;}/* * mesPrepareProfile: * * Parameters: * pMeProf Parameters for controlling ME * pRefFrm Reference frame buffer to provide frame information * encPar Encoding parameters (motion range, etc.) * nRefFrames Number of reference frames * * Function: * Prepare the structure for controlling the ME. * * Returns: * - */void mesPrepareProfile(meProfile_s *pMeProf, refFrmBuf_s *pRefFrm, encParams_s *encPar, int nRefFrames){ int i, j; // at least 1 reference frame pMeProf->area0[0] = pRefFrm->searchArea.x0; pMeProf->area1[0] = pRefFrm->searchArea.x1; pMeProf->area0[1] = pRefFrm->searchArea.y0; pMeProf->area1[1] = pRefFrm->searchArea.y1; // Hadamard transform is not used in MODE_DECISION_SIMPLE mode#ifndef DISABLE_RDO pMeProf->hadamard = ! ((encPar->rdo & 0x0F) == MODE_DECISION_SIMPLE); pMeProf->profile = (encPar->profile << 4) | ((encPar->rdo & 0x0F) == MODE_DECISION_RDO);#else pMeProf->hadamard = 1; pMeProf->profile = encPar->profile << 4;#endif pMeProf->interModeFlags = encPar->modeFlags; // from MOT_16x16 to MOT_4x4 // for reference frame 0, MOT_16x16 for (i = 0; i < 2; i ++) for (j = 0; j < 2; j ++) pMeProf->range[i][j] = (int16) (encPar->range * 4); // half range for other modes if (encPar->rangeMod & 1) for (j = 0; j < 2; j ++) pMeProf->range[1][j] >>= 1; // half range for other reference frames if (encPar->rangeMod & 2) for (i = 0; i < 2; i ++) pMeProf->range[i][1] >>= 1; for (i = 0; i < 2; i ++) for (j = 0; j < 2; j ++) if (pMeProf->range[i][j] < 16) // scaled up by 4 pMeProf->range[i][j] = 16; if ((pMeProf->profile >> 4) == PROF_CODING_SPEED) { pMeProf->searchCtrFlag = 0; pMeProf->pruneTreeFlag = 1; // 0 or 1 pMeProf->pruneThUnit = 5; pMeProf->subsampling = 8; // 4, 8, 16 } else { pMeProf->searchCtrFlag = 0;#ifndef DISABLE_RDO if ((encPar->rdo & 0x0F) == MODE_DECISION_RDO) pMeProf->pruneTreeFlag = 0; // 0 or 1 else#endif pMeProf->pruneTreeFlag = 1; // 0 or 1 pMeProf->pruneThUnit = 1; pMeProf->subsampling = 4; // 4, 8, 16 } // can not support this feature if there are multiple reference frames if (nRefFrames > 1) pMeProf->pruneTreeFlag = 0; // 0 or 1}int PrecomputeRefPointers(macroblock_s *pMb, refFrmBuf_s **refBufList, int nRefFrames, u_int8 *refBlkPtrs[][16], u_int16 *refPartSum[]){ int i, j; int refWidth; // pre-compute all the reference block pointers, refWidth = refBufList[0]->yBufWidth; for (i = 0; i < nRefFrames; i ++) { u_int8 *refMbPtr; refFrmBuf_s *pRefFrm; pRefFrm = refBufList[i]; refMbPtr = pRefFrm->y + (pMb->idxY * MBK_SIZE << 1) * refWidth + (pMb->idxX * MBK_SIZE << 1); // refPartSum is not used that often, so only compute the MB pointer refPartSum[i] = pRefFrm->partSums + (pMb->idxY * MBK_SIZE) * (refWidth >> 1) + (pMb->idxX * MBK_SIZE); for (j = 0; j < BLK_PER_MB * BLK_PER_MB; j ++) { int k; k = j % 4; refBlkPtrs[i][j] = refMbPtr + (k * BLK_SIZE << 1); if (k == 3) refMbPtr += refWidth * (BLK_SIZE << 1); } } return refWidth;}/* * mesBasicMode: * * Parameters: * pMb Macroblock information * pMeProf Parameters for controlling ME * mbPart Define a region within macroblock * refBlkPtrs Pointers to blocks in the reference MB * refPartSum Partial sum of blocks in reference MB * mode Prediction mode, define prediction block size * blkMvBits Number of MV bits of this block * * Function: * Search the best vectors for one of basic modes: 16x16, 16x8, 8x16, * 8x8, 8x4, 4x8, 4x4. * * Returns: * Minimal SAD for the MB or sub-MB being predicted. */static int mesBasicMode(macroblock_s *pMb, meProfile_s *pMeProf, mbPart_s *mbPart, u_int8 **refBlkPtrs, u_int16 *refPartSum, int mode, int *blkMvBits){ int bestLazyMode; int16 *blkSadsBuf; motVec_s predVec, bestVec; blkState_s *current; int mbPartSad, mpBlkAddr; mpBlkAddr = mbPart->y0 * BLK_PER_MB + mbPart->x0; current = & pMb->current[mbPart->y0][mbPart->x0]; blkSadsBuf = & pMeProf->blkSADs[current->ref][mode][0]; predVec = mcpFindPredMv(pMb, current->ref, mode, mpBlkAddr); mbPart->vlcMvBitsX = uvlcBitsSigned - predVec.x + 511; mbPart->vlcMvBitsY = uvlcBitsSigned - predVec.y + 511; // should we perform search at all? bestLazyMode = mode; mbPartSad = 0; // perform this only for the last reference frame if (pMeProf->pruneTreeFlag && (mode > MOT_16x16)) { mbPartSad = mesBlockLazyMatch( & pMeProf->blkSADs[0][MOT_16x16][mpBlkAddr], mode, & bestLazyMode); if (mbPartSad >= modeNumBlocks[mode] * pMeProf->pruneTreeTh) bestLazyMode = mode; // set it to the original mode //else bestLazyMode should be set to be < mode } if (bestLazyMode == mode) { mesDetermineSearchRegion(pMeProf, & predVec, pMb, mbPart); mbPart->orig = & pMb->origY[mbPart->y0 * BLK_SIZE][mbPart->x0 * BLK_SIZE]; // Motion block position in reference frame // y has been upsampled mbPart->ref = refBlkPtrs[mpBlkAddr]; if (mode <= MOT_8x8) { // SEA is only performed when size is 8x8 or up mbPart->partSum = (int *) pMb->partSums + mpBlkAddr; mbPart->refPartSum = refPartSum + (mbPart->y0 * BLK_SIZE) * (mbPart->refWidth >> 1) + (mbPart->x0 * BLK_SIZE); } if (pMeProf->lc3.low_complex_prof3) bestVec = mesFindMotionBlock_fast(mbPart, pMeProf, & mbPartSad ); else bestVec = mesFindMotionBlock(mbPart, pMeProf, & mbPartSad); // we will calculate the sad after Hadamard anyway if (pMeProf->hadamard) mbPartSad = findSATD4Blk(mbPart->orig, mbPart->ref, mbPart->refWidth, mbPart->width, mbPart->height, bestVec.x, bestVec.y, & blkSadsBuf[mpBlkAddr] ); else mbPartSad = findSAD4Blk(mbPart->orig, mbPart->ref, mbPart->refWidth, mbPart->width, mbPart->height, bestVec.x, bestVec.y, & blkSadsBuf[mpBlkAddr]); /* Favor 16x16 blocks that have zero motion */ if (mbPart->mode == MOT_16x16) { if ((bestVec.x | bestVec.y) == 0) mbPartSad -= mbPart->lambda * ZERO_VEC_SAD; } } else { // no additional search, but need to calculate SAD // get MV from skipMotVecs as the best vector, only need 1 MV as area // sharing the same vector in skipMotVecs always larger than size of // current partition, ME is from large to small partitions. // do not need to copy blkSADs and skipMotVecs to the current mode, // as blkSADs of the current mode has been set to a large value, // current mode will never be picked as a replacement. if (bestLazyMode < MOT_8x8) bestVec = pMb->modeMvRef[bestLazyMode][mpBlkAddr].mv; else bestVec = pMb->skipMVs[bestLazyMode - MOT_8x8][mpBlkAddr]; } // only need to copy this one position, others will be filled later current[0].mv = bestVec; // add the motion vector to the overall SAD *blkMvBits = mbPart->vlcMvBitsX[bestVec.x] + mbPart->vlcMvBitsY[bestVec.y]; mbPartSad += mbPart->lambda * (*blkMvBits); return mbPartSad;}int encoRecoBlock(u_int8 origBlk[][MBK_SIZE], u_int8 predBlk[][MBK_SIZE], int coeff[BLK_SIZE][BLK_SIZE], u_int8 *reco, int recoWidth, int picType, int qp);/* * mesMbPartCost: * * Parameters: * pMb Macroblock information * refBlkPtrs Pointers to blocks in the reference MB * refWidth Reference buffer width * mpX0 Addr of 1st 4x4 block, X * mpY0 Addr of 1st 4x4 block, Y * mbPartW Width of the MB partition, in 4x4 blocks * mbPartH Height of the MB partition, in 4x4 blocks * pMse For getting the MSE * * Function: * Evaluate the cost of encoding the MB partition. * * Returns: * Number of bits spent on encoding the MB partition. */int mesMbPartCost(macroblock_s *pMb, u_int8 *refBlkPtrs[16], int refWidth, int mpX0, int mpY0, int mbPartW, int mbPartH, int *pMse){ int i, j, bits, mse, numCoefs, numNonZeroBlks, nonZero; u_int8 predBlk[4][16], reco[16]; int coeff[4][4]; bits = 0; mse = 0; numNonZeroBlks = 0; for (j = mpY0; j < mpY0 + mbPartH; j ++) { for (i = mpX0; i < mpX0 + mbPartW; i ++) { u_int8 *origBlk, *refBlk; blkState_s *blkInfo; if (mbPartH + mbPartW == 4) // MOT_8x8 blkInfo = & pMb->current[j][i]; else blkInfo = & pMb->current[mpY0][mpX0]; origBlk = & pMb->origY[j * BLK_SIZE][i * BLK_SIZE]; // get the quarter-pixel interpolated luminance predictor refBlk = refBlkPtrs[j * 4 + i] + (blkInfo->mv.y >> 1) * refWidth + (blkInfo->mv.x >> 1); mcpGetQuarterPixels(refBlk, refWidth, blkInfo->mv.x, blkInfo->mv.y, 4, 4, predBlk); nonZero = encoRecoBlock((u_int8 (*)[MBK_SIZE]) origBlk, predBlk, coeff, reco, 4, SLICE_P, pMb->qp); if (nonZero) numNonZeroBlks ++; mse += CalculateSsd(origBlk, MBK_SIZE, reco, 4, BLK_SIZE, BLK_SIZE); bibInit(& pMb->mbBs); bits += streamSend4x4Blk(& pMb->mbBs, pMb, 1, COMP_LUMA, i, j, coeff, BLK_CAT_Y, & numCoefs); blkInfo->numLumaCoefs = (int8) numCoefs; } } if (numNonZeroBlks == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -