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

📄 motest.c

📁 Nokia H.264/AVC Encoder/Decoder Usage Manual
💻 C
📖 第 1 页 / 共 4 页
字号:
    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])&current[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 + -