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

📄 erc_do_p.c

📁 H264视频编解码程序
💻 C
📖 第 1 页 / 共 4 页
字号:
                buildPredRegionYUV(erc_img, mvPred, currRegion->xMin, currRegion->yMin, predMB);
              }
              
              /* measure absolute boundary pixel difference */
              currDist = edgeDistortion(predBlocks, 
                MBNum2YBlock(currMBNum,comp,picSizeX),
                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(struct img_par *img, int32 *mv, int x, int y, imgpel *predMB)
{
  int tmp_block[BLOCK_SIZE][BLOCK_SIZE];
  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 = max (mv[2], 0); // !!KS: quick fix, we sometimes seem to get negative ref_pic here, so restrict to zero an above

  /* 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(ref_frame, listX[0], vec1_x,vec1_y,img,tmp_block);

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

  for (i = 0; i < 16; i++)
  {
    for (j = 0; j < 16; j++)
    {
      pMB[i*16+j] = img->mpr[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_blk8x8_uv/2);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=max (0, min (i1/f1_x,   dec_picture->size_x_cr-1));
              jj0=max (0, min (j1/f1_y,   dec_picture->size_y_cr-1));
              ii1=max (0, min ((i1+f2_x)/f1_x, dec_picture->size_x_cr-1));
              jj1=max (0, min ((j1+f2_y)/f1_y, dec_picture->size_y_cr-1));
            
              if1=(i1 & f2_x);
              jf1=(j1 & f2_y);
              if0=f1_x-if1;
              jf0=f1_y-jf1;
            
              img->mpr[ii+ioff][jj+joff]=(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 (i = 0; i < 8; i++)
      {
        for (j = 0; j < 8; j++)
        {
          pMB[i*8+j] = img->mpr[j][i];
        }
      }
      pMB += 64;

    }
  }
}
/*!
 ************************************************************************
 * \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, 
                        int32 picSizeX, int32 regionSize) 
{
  
  int j, k, xmin, ymin, xmax, ymax;
  int32 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, int32 picSizeX, int32 regionSize)
{
  int i, j, distortion, numOfPredBlocks, threshold = ERC_BLOCK_OK;
  imgpel *currBlock = NULL, *neighbor = NULL;
  int32 currBlockOffset = 0;
  
  currBlock = recY + (yPosYBlock(currYBlockNum,picSizeX)<<3)*picSizeX + (xPosYBlock(currYBlockNum,picSizeX)<<3);
  
  do 
  {
    
    distortion = 0; numOfPredBlocks = 0;
    
    /* loop the 4 neighbours */
    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 += mabs((int)(predMB[i] - neighbor[i]));
          }
          break;          
        case 5:
          neighbor = currBlock - 1;
          for ( i = 0; i < regionSize; i++ ) 
          {
            distortion += mabs((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 += mabs((int)(predMB[i+currBlockOffset] - neighbor[i]));
          }
          break;                
        case 7:
          neighbor = currBlock + regionSize;
          currBlockOffset = regionSize-1;
          for ( i = 0; i < regionSize; i++ ) 
          {
            distortion += mabs((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(struct img_par *img, int32 *mv, 
                                    int x, int y, imgpel *predMB, int list)
{
    int tmp_block[BLOCK_SIZE][BLOCK_SIZE];
    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];

    /* 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(ref_frame, listX[list], vec1_x,vec1_y,img,tmp_block);

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


    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            pMB[i*4+j] = img->mpr[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;

⌨️ 快捷键说明

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