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

📄 errdo.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 2 页
字号:
{
  int i,j,k;
  int block_size_x, block_size_y;
  int mv_mode, pred_dir;
  static const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};
  int block8x8;
  int k_start, k_end, k_inc;

  if (!currMB->mb_type)
  {
    block_size_x = MB_BLOCK_SIZE;
    block_size_y = MB_BLOCK_SIZE;
    pred_dir = LIST_0;

    perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, 0, 0, block_size_x, block_size_y);
  }
  else if (currMB->mb_type == 1)
  {
    block_size_x = MB_BLOCK_SIZE;
    block_size_y = MB_BLOCK_SIZE;
    pred_dir = currMB->b8pdir[0];   

    perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, 0, 0, block_size_x, block_size_y);
  }
  else if (currMB->mb_type == 2)
  {   
    block_size_x = MB_BLOCK_SIZE;
    block_size_y = 8;    

    for (block8x8 = 0; block8x8 < 4; block8x8 += 2)
    {
      pred_dir = currMB->b8pdir[block8x8];
      perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, 0, block8x8, block_size_x, block_size_y);
    }
  }
  else if (currMB->mb_type == 3)
  {   
    block_size_x = 8;
    block_size_y = 16;

    for (block8x8 = 0; block8x8 < 2; block8x8++)
    {
      i = block8x8<<1;
      j = 0;      
      pred_dir = currMB->b8pdir[block8x8];
      assert (pred_dir<=2);
      perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, i, j, block_size_x, block_size_y);
    }
  }
  else //Need to change to support B slices.
  {
    for (block8x8 = 0; block8x8 < 4; block8x8++)
    {
      mv_mode  = currMB->b8mode[block8x8];
      pred_dir = currMB->b8pdir[block8x8];

      if ( mv_mode != 0 )
      {
        k_start = (block8x8 << 2);
        k_inc = (mv_mode == 5) ? 2 : 1;
        k_end = (mv_mode == 4) ? k_start + 1 : ((mv_mode == 7) ? k_start + 4 : k_start + k_inc + 1);

        block_size_x = ( mv_mode == 5 || mv_mode == 4 ) ? 8 : 4;
        block_size_y = ( mv_mode == 6 || mv_mode == 4 ) ? 8 : 4;

        for (k = k_start; k < k_end; k += k_inc)
        {
          i =  (decode_block_scan[k] & 3);
          j = ((decode_block_scan[k] >> 2) & 3);
          perform_mc_concealment(decoder, PLANE_Y, enc_pic, image, pred_dir, i, j, block_size_x, block_size_y);
        }        
      }
    }
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Performs copy error concealment for macroblocks with errors.
 *  Note: Currently assumes that the reference picture lists remain the same for all 
 *        slices of a picture. 
 *  
 *************************************************************************************
 */
void copy_conceal_picture(ImageParameters *image, StorablePicture *enc_pic, int decoder)
{
  unsigned int mb;
  Macroblock* currMB;
  int mb_error;
  byte** mb_error_map = enc_pic->mb_error_map[decoder];
  StorablePicture* refPic;

  refPic = find_nearest_ref_picture(enc_pic->poc); //Used for concealment if actual reference pic is not known.

  for (mb = 0; mb < image->PicSizeInMbs; mb++)
  {
    image->mb_x = PicPos[mb][0];
    image->mb_y = PicPos[mb][1];
    mb_error = mb_error_map[image->mb_y][image->mb_x];
    if (mb_error)
    {
      currMB = &image->mb_data[mb];
      image->block_x = image->mb_x << 2;
      image->block_y = image->mb_y << 2;
      image->pix_x   = image->block_x << 2;
      image->pix_y   = image->block_y << 2;
      copy_conceal_mb(enc_pic, image, decoder, mb_error, currMB, refPic);
    }
  }
}

/******************************************************************************************
*
* Perform copy error concealment for macroblock.
*   
*******************************************************************************************
*/
static void copy_conceal_mb(StorablePicture *enc_pic, ImageParameters* image, int decoder, int mb_error, Macroblock* currMB, StorablePicture* refPic)
{
  int j, i0 = img->pix_x;
  imgpel** concealed_img = &(enc_pic->p_dec_img[0][decoder][image->pix_y]);
  imgpel** ref_img;

  if (mb_error == 1 || (mb_error != 3 && currMB->mb_type > P8x8)) //All partitions lost, or intra mb lost
  {
    if (refPic != NULL) //Use nearest reference picture for concealment
    {
      ref_img = &(refPic->p_dec_img[0][decoder][img->pix_y]);
      for (j = 0; j < MB_BLOCK_SIZE; j++)
      {
        memcpy(&(concealed_img[j][i0]), &(ref_img[j][i0]), sizeof(imgpel)*MB_BLOCK_SIZE);
      }
    }
    else //No ref picture available
    {
      for (j = 0; j < MB_BLOCK_SIZE; j++)
      {
        memset(&(concealed_img[j][i0]), 128, sizeof(imgpel)*MB_BLOCK_SIZE); //Only reliable if sizeof(imgpel) = 1
      }
    }
  }
  else if (mb_error != 2 && image->type == P_SLICE && currMB->mb_type && currMB->mb_type < P8x8) //Only partition 3 lost, and P macroblock and not skip
  {
    get_predicted_concealment_mb(enc_pic, image, decoder, currMB);
    for(j = 0; j < MB_BLOCK_SIZE; j++)
    {                
      memcpy(&(concealed_img[j][i0]), &(image->mb_pred[j][0]), MB_BLOCK_SIZE * sizeof(imgpel));
    }
  }
}

/******************************************************************************************
*
*  Finds reference picture with nearest POC to current picture to use for error concealment
*   
*******************************************************************************************
*/
static StorablePicture* find_nearest_ref_picture(int poc)
{
  unsigned int i;
  int min_poc_diff = 1000;
  int poc_diff;
  StorablePicture* refPic = NULL;

  for (i = 0; i < dpb.ref_frames_in_buffer; i++)
  {
    if (dpb.fs_ref[i]->is_used==3)
    {
      if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
      {
        poc_diff = iabs(dpb.fs_ref[i]->frame->poc - poc);
        if (poc_diff < min_poc_diff)
        {
          refPic = dpb.fs_ref[i]->frame;
          min_poc_diff = poc_diff;
        }
      }
    }
  }
  return refPic;
}

/*!
 *************************************************************************************
 * \brief
 *    Gives the prediction residue for a block
 *************************************************************************************
 */
void compute_residue_block (ImageParameters *image, imgpel **imgY, int res_img[16][16], imgpel mb_pred[16][16], int b8block, int block_size) 
{
  int i,j;
  int i0 = (b8block & 0x01)<<3,   i1 = i0+block_size;
  int j0 = (b8block >> 1)<<3,     j1 = j0+block_size;
  //imgpel  (*mb_pred)[16]        = (i16mode >= 0) ? image->mpr_16x16[0][i16mode] : image->mb_pred[0];;

  for (i = i0; i < i1; i++)
  {
    for (j = j0; j < j1; j++)
    {
      res_img[j][i] = (int)imgY[j][image->pix_x + i] - mb_pred[j][i];
    } 
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Stores the pel values for the current best mode.
 *************************************************************************************
 */
void errdo_store_best_block(ImageParameters* image, imgpel*** mbY, imgpel*** dec_img, int i0, int j0, int block_size)
{
  int j, k;
  int i = image->pix_x + i0;
  int j1 = j0 + block_size;
  
  for (k = 0; k < params->NoOfDecoders; k++)
  {
    for (j = j0; j < j1; j++)
    {
      memcpy(&mbY[k][j][i0], &dec_img[k][image->pix_y + j][i], block_size * sizeof(imgpel));
    }
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Restores the pel values from the current best 8x8 mode.
 *************************************************************************************
 */
void errdo_get_best_block(ImageParameters* image, imgpel*** dec_img, imgpel*** mbY, int j0, int block_size)
{
  int j, k;
  int j1 = j0 + block_size;

  for (k = 0; k < params->NoOfDecoders; k++)
  {
    for (j = j0; j < j1; j++)
    {
      memcpy(&dec_img[k][image->pix_y + j][image->pix_x], mbY[k][j], block_size * sizeof(imgpel));
    }
  }
}

/*!
 *************************************************************************************
 * \brief
 *    Builds a random status map showing whether each MB is received or lost, based
 *    on the packet loss rate and the slice structure.
 *
 * \param s_map
 *    The status map to be filled
 *************************************************************************************
 */
static void Build_Status_Map(byte **s_map)
{
  int i,j,slice=-1,mb=0,jj,ii,packet_lost=0;

  jj = img->height/MB_BLOCK_SIZE;
  ii = img->width/MB_BLOCK_SIZE;

  for (j = 0; j < jj; j++)
  {
    for (i = 0; i < ii; i++)
    {
      if (!params->slice_mode || img->mb_data[mb].slice_nr != slice) /* new slice */
      {
        packet_lost=0;
        if ((double)rand()/(double)RAND_MAX*100 < params->LossRateC)   packet_lost += 3;
        if ((double)rand()/(double)RAND_MAX*100 < params->LossRateB)   packet_lost += 2;
        if ((double)rand()/(double)RAND_MAX*100 < params->LossRateA)   packet_lost  = 1;
        slice++;
      }
      if (!packet_lost)
      {
        s_map[j][i]=0;  //! Packet OK
      }
      else
      {
        s_map[j][i]=packet_lost;
        if(params->partition_mode == 0)  s_map[j][i]=1;
      }
      mb++;
    }
  }
}

⌨️ 快捷键说明

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