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

📄 erc_do_p.c

📁 H.264基于baseline解码器的C++实现源码
💻 C
📖 第 1 页 / 共 4 页
字号:
                predMB, recfr->yptr, picSizeX, regionSize);

              /* if so far best -> store the pixels as the best concealment */
              if (currDist < minDist || !fInterNeighborExists)
              {

                minDist = currDist;
                bestDir = i;

                for (k=0;k<3;k++)
                  mvBest[k] = mvPred[k];

                currRegion->regionMode =
                  (isBlock(object_list, predMBNum, compPred, INTER_COPY)) ?
                  ((regionSize == 16) ? REGMODE_INTER_COPY : REGMODE_INTER_COPY_8x8) :
                  ((regionSize == 16) ? REGMODE_INTER_PRED : REGMODE_INTER_PRED_8x8);

                copyPredMB(MBNum2YBlock(currMBNum,comp,picSizeX), predMB, recfr,
                  picSizeX, regionSize);
              }

              fInterNeighborExists = 1;
            }
          }
        }
    }

    threshold--;

    } while ((threshold >= ERC_BLOCK_CONCEALED) && (fInterNeighborExists == 0));

    /* always try zero motion */
    if (!fZeroMotionChecked)
    {
      mvPred[0] = mvPred[1] = 0;
      mvPred[2] = 0;

      buildPredRegionYUV(erc_img, mvPred, currRegion->xMin, currRegion->yMin, predMB);

      currDist = edgeDistortion(predBlocks,
        MBNum2YBlock(currMBNum,comp,picSizeX),
        predMB, recfr->yptr, picSizeX, regionSize);

      if (currDist < minDist || !fInterNeighborExists)
      {

        minDist = currDist;
        for (k=0;k<3;k++)
          mvBest[k] = mvPred[k];

        currRegion->regionMode =
          ((regionSize == 16) ? REGMODE_INTER_COPY : REGMODE_INTER_COPY_8x8);

        copyPredMB(MBNum2YBlock(currMBNum,comp,picSizeX), predMB, recfr,
          picSizeX, regionSize);
      }
    }

    for (i=0; i<3; i++)
      currRegion->mv[i] = mvBest[i];

    yCondition[MBNum2YBlock(currMBNum,comp,picSizeX)] = ERC_BLOCK_CONCEALED;
    comp = (comp+order+4)%4;
    compLeft--;

    } while (compLeft);

    return 0;
}

/*!
************************************************************************
* \brief
*      Builds the motion prediction pixels from the given location (in 1/4 pixel units)
*      of the reference frame. It not only copies the pixel values but builds the interpolation
*      when the pixel positions to be copied from is not full pixel (any 1/4 pixel position).
*      It copies the resulting pixel vlaues into predMB.
* \param img
*      The pointer of img_par struture of current frame
* \param mv
*      The pointer of the predicted MV of the current (being concealed) MB
* \param x
*      The x-coordinate of the above-left corner pixel of the current MB
* \param y
*      The y-coordinate of the above-left corner pixel of the current MB
* \param predMB
*      memory area for storing temporary pixel values for a macroblock
*      the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
************************************************************************
*/
static void buildPredRegionYUV(ImageParameters *img, int *mv, int x, int y, imgpel *predMB)
{
  static imgpel **tmp_block;
  int i=0, j=0, ii=0, jj=0,i1=0,j1=0,j4=0,i4=0;
  int jf=0;
  int uv;
  int vec1_x=0,vec1_y=0;
  int ioff,joff;
  imgpel *pMB = predMB;

  int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0;
  int mv_mul;

  //FRExt
  int f1_x, f1_y, f2_x, f2_y, f3, f4, ifx;
  int b8, b4;
  int yuv = dec_picture->chroma_format_idc - 1;

  int ref_frame = imax (mv[2], 0); // !!KS: quick fix, we sometimes seem to get negative ref_pic here, so restrict to zero and above

  // This should be allocated only once. 
  get_mem2Dpel(&tmp_block, MB_BLOCK_SIZE, MB_BLOCK_SIZE);

  /* Update coordinates of the current concealed macroblock */
  img->mb_x = x/MB_BLOCK_SIZE;
  img->mb_y = y/MB_BLOCK_SIZE;
  img->block_y = img->mb_y * BLOCK_SIZE;
  img->pix_c_y = img->mb_y * img->mb_cr_size_y;
  img->block_x = img->mb_x * BLOCK_SIZE;
  img->pix_c_x = img->mb_x * img->mb_cr_size_x;

  mv_mul=4;

  // luma *******************************************************

  for(j=0;j<MB_BLOCK_SIZE/BLOCK_SIZE;j++)
  {
    joff=j*4;
    j4=img->block_y+j;
    for(i=0;i<MB_BLOCK_SIZE/BLOCK_SIZE;i++)
    {
      ioff=i*4;
      i4=img->block_x+i;

      vec1_x = i4*4*mv_mul + mv[0];
      vec1_y = j4*4*mv_mul + mv[1];

      get_block_luma(PLANE_Y, listX[0][ref_frame], vec1_x, vec1_y, BLOCK_SIZE, BLOCK_SIZE, img, tmp_block);  

      for(ii=0;ii<BLOCK_SIZE;ii++)
        for(jj=0;jj<MB_BLOCK_SIZE/BLOCK_SIZE;jj++)
          img->mb_pred[LumaComp][jj+joff][ii+ioff]=tmp_block[jj][ii];
    }
  }


  for (j = 0; j < 16; j++)
  {
    for (i = 0; i < 16; i++)
    {
      pMB[j*16+i] = img->mb_pred[LumaComp][j][i];
    }
  }
  pMB += 256;

  if (dec_picture->chroma_format_idc != YUV400)
  {
    // chroma *******************************************************
    f1_x = 64/img->mb_cr_size_x;
    f2_x=f1_x-1;

    f1_y = 64/img->mb_cr_size_y;
    f2_y=f1_y-1;

    f3=f1_x*f1_y;
    f4=f3>>1;

    for(uv=0;uv<2;uv++)
    {
      for (b8=0;b8<(img->num_uv_blocks);b8++)
      {
        for(b4=0;b4<4;b4++)
        {
          joff = subblk_offset_y[yuv][b8][b4];
          j4=img->pix_c_y+joff;
          ioff = subblk_offset_x[yuv][b8][b4];
          i4=img->pix_c_x+ioff;

          for(jj=0;jj<4;jj++)
          {
            jf=(j4+jj)/(img->mb_cr_size_y/4);     // jf  = Subblock_y-coordinate
            for(ii=0;ii<4;ii++)
            {
              ifx=(i4+ii)/(img->mb_cr_size_x/4);  // ifx = Subblock_x-coordinate

              i1=(i4+ii)*f1_x + mv[0];
              j1=(j4+jj)*f1_y + mv[1];

              ii0=iClip3 (0, dec_picture->size_x_cr-1, i1/f1_x);
              jj0=iClip3 (0, dec_picture->size_y_cr-1, j1/f1_y);
              ii1=iClip3 (0, dec_picture->size_x_cr-1, ((i1+f2_x)/f1_x));
              jj1=iClip3 (0, dec_picture->size_y_cr-1, ((j1+f2_y)/f1_y));

              if1=(i1 & f2_x);
              jf1=(j1 & f2_y);
              if0=f1_x-if1;
              jf0=f1_y-jf1;

              img->mb_pred[uv + 1][jj+joff][ii+ioff]=(if0*jf0*listX[0][ref_frame]->imgUV[uv][jj0][ii0]+
                if1*jf0*listX[0][ref_frame]->imgUV[uv][jj0][ii1]+
                if0*jf1*listX[0][ref_frame]->imgUV[uv][jj1][ii0]+
                if1*jf1*listX[0][ref_frame]->imgUV[uv][jj1][ii1]+f4)/f3;
            }
          }
        }
      }

      for (j = 0; j < 8; j++)
      {
        for (i = 0; i < 8; i++)
        {
          pMB[j*8+i] = img->mb_pred[uv + 1][j][i];
        }
      }
      pMB += 64;

    }
  }
  // We should allocate this memory only once.
  free_mem2Dpel(tmp_block); 
}
/*!
 ************************************************************************
 * \brief
 *      Copies pixel values between a YUV frame and the temporary pixel value storage place. This is
 *      used to save some pixel values temporarily before overwriting it, or to copy back to a given
 *      location in a frame the saved pixel values.
 * \param currYBlockNum
 *      index of the block (8x8) in the Y plane
 * \param predMB
 *      memory area where the temporary pixel values are stored
 *      the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
 * \param recfr
 *      pointer to a YUV frame
 * \param picSizeX
 *      picture width in pixels
 * \param regionSize
 *      can be 16 or 8 to tell the dimension of the region to copy
 ************************************************************************
 */
static void copyPredMB (int currYBlockNum, imgpel *predMB, frame *recfr,
                        int picSizeX, int regionSize)
{

  int j, k, xmin, ymin, xmax, ymax;
  int locationTmp, locationPred;
  int uv_x = uv_div[0][dec_picture->chroma_format_idc];
  int uv_y = uv_div[1][dec_picture->chroma_format_idc];

  xmin = (xPosYBlock(currYBlockNum,picSizeX)<<3);
  ymin = (yPosYBlock(currYBlockNum,picSizeX)<<3);
  xmax = xmin + regionSize -1;
  ymax = ymin + regionSize -1;

  for (j = ymin; j <= ymax; j++)
  {
    for (k = xmin; k <= xmax; k++)
    {
      locationPred = j * picSizeX + k;
      locationTmp = (j-ymin) * 16 + (k-xmin);
      dec_picture->imgY[j][k] = predMB[locationTmp];
    }
  }

  if (dec_picture->chroma_format_idc != YUV400)
  {
    for (j = (ymin>>uv_y); j <= (ymax>>uv_y); j++)
    {
      for (k = (xmin>>uv_x); k <= (xmax>>uv_x); k++)
      {
        locationPred = ((j * picSizeX) >> uv_x) + k;
        locationTmp = (j-(ymin>>uv_y)) * img->mb_cr_size_x + (k-(xmin>>1)) + 256;
        dec_picture->imgUV[0][j][k] = predMB[locationTmp];

        locationTmp += 64;

        dec_picture->imgUV[1][j][k] = predMB[locationTmp];
      }
    }
  }
}

/*!
 ************************************************************************
 * \brief
 *      Calculates a weighted pixel difference between edge Y pixels of the macroblock stored in predMB
 *      and the pixels in the given Y plane of a frame (recY) that would become neighbor pixels if
 *      predMB was placed at currYBlockNum block position into the frame. This "edge distortion" value
 *      is used to determine how well the given macroblock in predMB would fit into the frame when
 *      considering spatial smoothness. If there are correctly received neighbor blocks (status stored
 *      in predBlocks) only they are used in calculating the edge distorion; otherwise also the already
 *      concealed neighbor blocks can also be used.
 * \return
 *      The calculated weighted pixel difference at the edges of the MB.
 * \param predBlocks
 *      status array of the neighboring blocks (if they are OK, concealed or lost)
 * \param currYBlockNum
 *      index of the block (8x8) in the Y plane
 * \param predMB
 *      memory area where the temporary pixel values are stored
 *      the Y,U,V planes are concatenated y = predMB, u = predMB+256, v = predMB+320
 * \param recY
 *      pointer to a Y plane of a YUV frame
 * \param picSizeX
 *      picture width in pixels
 * \param regionSize
 *      can be 16 or 8 to tell the dimension of the region to copy
 ************************************************************************
 */
static int edgeDistortion (int predBlocks[], int currYBlockNum, imgpel *predMB,
                           imgpel *recY, int picSizeX, int regionSize)
{
  int i, j, distortion, numOfPredBlocks, threshold = ERC_BLOCK_OK;
  imgpel *currBlock = NULL, *neighbor = NULL;
  int currBlockOffset = 0;

  currBlock = recY + (yPosYBlock(currYBlockNum,picSizeX)<<3)*picSizeX + (xPosYBlock(currYBlockNum,picSizeX)<<3);

  do
  {

    distortion = 0; numOfPredBlocks = 0;

    // loop the 4 neighbors
    for (j = 4; j < 8; j++)
    {
      /* if reliable, count boundary pixel difference */
      if (predBlocks[j] >= threshold)
      {

        switch (j)
        {
        case 4:
          neighbor = currBlock - picSizeX;
          for ( i = 0; i < regionSize; i++ )
          {
            distortion += iabs((int)(predMB[i] - neighbor[i]));
          }
          break;
        case 5:
          neighbor = currBlock - 1;
          for ( i = 0; i < regionSize; i++ )
          {
            distortion += iabs((int)(predMB[i*16] - neighbor[i*picSizeX]));
          }
          break;
        case 6:
          neighbor = currBlock + regionSize*picSizeX;
          currBlockOffset = (regionSize-1)*16;
          for ( i = 0; i < regionSize; i++ )
          {
            distortion += iabs((int)(predMB[i+currBlockOffset] - neighbor[i]));
          }
          break;
        case 7:
          neighbor = currBlock + regionSize;
          currBlockOffset = regionSize-1;
          for ( i = 0; i < regionSize; i++ )
          {
            distortion += iabs((int)(predMB[i*16+currBlockOffset] - neighbor[i*picSizeX]));
          }
          break;
        }

        numOfPredBlocks++;
      }
    }

    threshold--;
    if (threshold < ERC_BLOCK_CONCEALED)
      break;
  } while (numOfPredBlocks == 0);

  if(numOfPredBlocks == 0)
  {
    return 0;
    // assert (numOfPredBlocks != 0); !!!KS hmm, trying to continue...
  }
  return (distortion/numOfPredBlocks);
}

// picture error concealment below

/*!
************************************************************************
* \brief
* The motion prediction pixels are calculated from the given location (in
* 1/4 pixel units) of the referenced frame. It copies the sub block from the
* corresponding reference to the frame to be concealed.
*
*************************************************************************
*/
static void buildPredblockRegionYUV(ImageParameters *img, int *mv,
                                    int x, int y, imgpel *predMB, int list)
{
  static imgpel **tmp_block;
  int i=0,j=0,ii=0,jj=0,i1=0,j1=0,j4=0,i4=0;
  int jf=0;
  int uv;
  int vec1_x=0,vec1_y=0;
  int ioff,joff;
  imgpel *pMB = predMB;

  int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0;
  int mv_mul;

  //FRExt
  int f1_x, f1_y, f2_x, f2_y, f3, f4, ifx;
  int yuv = dec_picture->chroma_format_idc - 1;

  int ref_frame = mv[2];

  get_mem2Dpel(&tmp_block, MB_BLOCK_SIZE, MB_BLOCK_SIZE);

  /* Update coordinates of the current concealed macroblock */

  img->mb_x = x/BLOCK_SIZE;
  img->mb_y = y/BLOCK_SIZE;
  img->block_y = img->mb_y * BLOCK_SIZE;
  img->pix_c_y = img->mb_y * img->mb_cr_size_y/4;
  img->block_x = img->mb_x * BLOCK_SIZE;
  img->pix_c_x = img->mb_x * img->mb_cr_size_x/4;

  mv_mul=4;

  // luma *******************************************************

  vec1_x = x*mv_mul + mv[0];
  vec1_y = y*mv_mul + mv[1];
  get_block_luma(PLANE_Y, listX[list][ref_frame], vec1_x,vec1_y, BLOCK_SIZE, BLOCK_SIZE, img, tmp_block);  

  for(jj=0;jj<MB_BLOCK_SIZE/BLOCK_SIZE;jj++)
    for(ii=0;ii<BLOCK_SIZE;ii++)
      img->mb_pred[LumaComp][jj][ii]=tmp_block[jj][ii];


  for (j = 0; j < 4; j++)
  {
    for (i = 0; i < 4; i++)
    {
      pMB[j*4+i] = img->mb_pred[LumaComp][j][i];
    }
  }
  pMB += 16;

  if (dec_picture->chroma_format_idc != YUV400)
  {
    // chroma *******************************************************
    f1_x = 64/(img->mb_cr_size_x);
    f2_x=f1_x-1;

    f1_y = 64/(img->mb_cr_size_y);
    f2_y=f1_y-1;

    f3=f1_x*f1_y;
    f4=f3>>1;

    for(uv=0;uv<2;uv++)

⌨️ 快捷键说明

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