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

📄 macroblock.c

📁 H.264基于baseline解码器的C++实现源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 ************************************************************************
 */
static void interpret_mb_mode_SI(Macroblock *currMB)
{
  const int ICBPTAB[6] = {0,16,32,15,31,47};
  int         mbmode   = currMB->mb_type;

  if (mbmode==0)
  {
    currMB->mb_type = SI4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
    img->siblock[img->mb_y][img->mb_x]=1;
  }
  else if (mbmode==1)
  {
    currMB->mb_type = I4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else if(mbmode==26)
  {
    currMB->mb_type=IPCM;
    currMB->cbp= -1;
    currMB->i16mode = 0;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }

  else
  {
    currMB->mb_type = I16MB;
    currMB->cbp= ICBPTAB[(mbmode-1)>>2];
    currMB->i16mode = (mbmode-2) & 0x03;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
}

/*!
 ************************************************************************
 * \brief
 *    Set mode interpretation based on slice type
 ************************************************************************
 */
void set_interpret_mb_mode(int slice_type)
{
  switch (slice_type)
  {
  case P_SLICE: case SP_SLICE:
    interpret_mb_mode = interpret_mb_mode_P;
    break;
  case B_SLICE:
    interpret_mb_mode = interpret_mb_mode_B;
    break;
  case I_SLICE: 
    interpret_mb_mode = interpret_mb_mode_I;
    break;
  case SI_SLICE: 
    interpret_mb_mode = interpret_mb_mode_SI;
    break;
  default:
    printf("Unsupported slice type\n");
    break;
  }
}
/*!
 ************************************************************************
 * \brief
 *    init macroblock I and P frames
 ************************************************************************
 */
static void init_macroblock(ImageParameters *img)
{
  int i, j, k;
  PicMotionParams *motion = &dec_picture->motion;
  for(j = img->block_y; j < img->block_y + BLOCK_SIZE; j++)
    memset(&img->ipredmode[j][img->block_x], DC_PRED, BLOCK_SIZE * sizeof(char));

  for (k = LIST_0; k <= LIST_1; k++)
  {
    // reset vectors and pred. modes
    for(j = img->block_y; j < img->block_y + BLOCK_SIZE; j++)
    {                           
      memset(&motion->mv[k][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
    }

    for(j = img->block_y; j < img->block_y + BLOCK_SIZE; j++)
    {
      memset(&motion->ref_idx[k][j][img->block_x], -1, BLOCK_SIZE * sizeof(char));
    }

    for(j = img->block_y; j < img->block_y + BLOCK_SIZE; j++)
    {
      for (i = img->block_x; i < img->block_x + BLOCK_SIZE;i++)
      {
        motion->ref_pic_id[k][j][i] = INT64_MIN;
      }
    }
  }
}


/*!
 ************************************************************************
 * \brief
 *    Sets mode for 8x8 block
 ************************************************************************
 */
void SetB8Mode (ImageParameters* img, Macroblock* currMB, int value, int i)
{
  static const char p_v2b8 [ 5] = {4, 5, 6, 7, IBLOCK};
  static const char p_v2pd [ 5] = {0, 0, 0, 0, -1};
  static const char b_v2b8 [14] = {0, 4, 4, 4, 5, 6, 5, 6, 5, 6, 7, 7, 7, IBLOCK};
  static const char b_v2pd [14] = {2, 0, 1, 2, 0, 0, 1, 1, 2, 2, 0, 1, 2, -1};

  if (img->type==B_SLICE)
  {
    currMB->b8mode[i] = b_v2b8[value];
    currMB->b8pdir[i] = b_v2pd[value];
  }
  else
  {
    currMB->b8mode[i] = p_v2b8[value];
    currMB->b8pdir[i] = p_v2pd[value];
  }
}


void reset_coeffs(void)
{
  // reset all coeffs
  //memset(&img->fcf[0][0][0], 0, 3 * MB_PIXELS * sizeof(int));
  memset(&img->cof[0][0][0], 0, 3 * MB_PIXELS * sizeof(int));

  // CAVLC
  if (active_pps->entropy_coding_mode_flag == UVLC)
    memset(&img->nz_coeff[img->current_mb_nr][0][0][0], 0, 3 * BLOCK_SIZE * BLOCK_SIZE * sizeof(byte));
}

void field_flag_inference(Macroblock *currMB)
{
  if (currMB->mbAvailA)
  {
    currMB->mb_field = img->mb_data[currMB->mbAddrA].mb_field;
  }
  else
  {
    // check top macroblock pair
    currMB->mb_field = currMB->mbAvailB ? img->mb_data[currMB->mbAddrB].mb_field : 0;
  }
}


void skip_macroblock(ImageParameters *img, Macroblock *currMB)
{
  short pred_mv[2];
  int zeroMotionAbove;
  int zeroMotionLeft;
  static PixelPos mb_a, mb_b, mb_c, mb_d;  // neighbor blocks
  int   i, j;
  int   a_mv_y = 0;
  int   a_ref_idx = 0;
  int   b_mv_y = 0;
  int   b_ref_idx = 0;
  int   img_block_y   = img->block_y;
  int   list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr & 0x01) ? 4 : 2 : 0;
  PicMotionParams *motion = &dec_picture->motion;
  static short *a_mv = NULL;
  static short *b_mv = NULL;

  get_neighbors(currMB, &mb_a, &mb_b, &mb_c, &mb_d, 0, 0, MB_BLOCK_SIZE);

  if (mb_a.available)
  {
    a_mv      = motion->mv[LIST_0][mb_a.pos_y][mb_a.pos_x];
    a_mv_y    = a_mv[1];    
    a_ref_idx = motion->ref_idx[LIST_0][mb_a.pos_y][mb_a.pos_x];

    if (currMB->mb_field && !img->mb_data[mb_a.mb_addr].mb_field)
    {
      a_mv_y    /=2;
      a_ref_idx *=2;
    }
    if (!currMB->mb_field && img->mb_data[mb_a.mb_addr].mb_field)
    {
      a_mv_y    *=2;
      a_ref_idx >>=1;
    }
  }

  if (mb_b.available)
  {
    b_mv      = motion->mv[LIST_0][mb_b.pos_y][mb_b.pos_x];
    b_mv_y    = b_mv[1];
    b_ref_idx = motion->ref_idx[LIST_0][mb_b.pos_y][mb_b.pos_x];

    if (currMB->mb_field && !img->mb_data[mb_b.mb_addr].mb_field)
    {
      b_mv_y    /=2;
      b_ref_idx *=2;
    }
    if (!currMB->mb_field && img->mb_data[mb_b.mb_addr].mb_field)
    {
      b_mv_y    *=2;
      b_ref_idx >>=1;
    }
  }

  zeroMotionLeft  = !mb_a.available ? 1 : a_ref_idx==0 && a_mv[0]==0 && a_mv_y==0 ? 1 : 0;
  zeroMotionAbove = !mb_b.available ? 1 : b_ref_idx==0 && b_mv[0]==0 && b_mv_y==0 ? 1 : 0;

  currMB->cbp = 0;
  reset_coeffs();

  if (zeroMotionAbove || zeroMotionLeft)
  {
    for(j = img_block_y; j < img_block_y + BLOCK_SIZE;j++)
    {
      memset(&motion->mv[LIST_0][j][img->block_x][0], 0, 2 * BLOCK_SIZE * sizeof(short));
    }
  }
  else
  {
    GetMotionVectorPredictor (currMB, &mb_a, &mb_b, &mb_c, pred_mv, 0, motion->ref_idx[LIST_0], motion->mv[LIST_0], 0, 0, MB_BLOCK_SIZE, MB_BLOCK_SIZE);

    // Set first block line (position img_block_y)
    for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
      memcpy(&motion->mv[LIST_0][img_block_y][i][0], &pred_mv[0], 2 * sizeof(short));

    // Now set remaining lines
    for(j=img_block_y; j < img_block_y + BLOCK_SIZE - 1;j++)
    {        
      memcpy(&motion->mv[LIST_0][j + 1][img->block_x][0], &motion->mv[LIST_0][j][img->block_x][0], 2 * BLOCK_SIZE * sizeof(short));
    }
  }
  
  // set reference index to 0
  for(j=img_block_y;j< img_block_y + BLOCK_SIZE;j++)
  {
    memset(&motion->ref_idx[LIST_0][j][img->block_x], 0, BLOCK_SIZE * sizeof(char));
  }  

  // Now set ref_pic_id
  // First line
  for(i=img->block_x;i<img->block_x + BLOCK_SIZE;i++)
  {        
    motion->ref_pic_id[LIST_0][img_block_y][i] =
      dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][0];
  }
  // remaining lines
  for(j=img_block_y;j< img_block_y + BLOCK_SIZE - 1;j++)
  {
    memcpy(&motion->ref_pic_id[LIST_0][j + 1][img->block_x], &motion->ref_pic_id[LIST_0][j][img->block_x], BLOCK_SIZE * sizeof(int64));
  }  
}

static void concealIPCMcoeffs(ImageParameters *img)
{
  int i, j, k;

  for(i=0;i<MB_BLOCK_SIZE;i++)
  {
    for(j=0;j<MB_BLOCK_SIZE;j++)
    {
      img->cof[0][i][j] = img->dc_pred_value_comp[0];
      //img->fcf[0][i][j] = img->dc_pred_value_comp[0];
    }
  }

  if ((dec_picture->chroma_format_idc != YUV400) && !IS_INDEPENDENT(img))
  {
    for (k = 0; k < 2; k++)
    {
      for(i=0;i<img->mb_cr_size_y;i++)
      {
        for(j=0;j<img->mb_cr_size_x;j++)
        {
          img->cof[k][i][j] = img->dc_pred_value_comp[k];
          //img->fcf[k][i][j] = img->dc_pred_value_comp[k];
        }
      }
    }
  }
}


/*!
 ************************************************************************
 * \brief
 *    Get the syntax elements from the NAL
 ************************************************************************
 */
void read_one_macroblock(ImageParameters *img, Slice *currSlice, Macroblock *currMB)
{
  int i;

  SyntaxElement currSE;
  int mb_nr = img->current_mb_nr; 

  DataPartition *dP;
  byte *partMap = assignSE2partition[currSlice->dp_mode];
  Macroblock *topMB = NULL;
  int  prevMbSkipped = 0;
  int  check_bottom, read_bottom, read_top;  
  PicMotionParams *motion = &dec_picture->motion;

  if (img->MbaffFrameFlag)
  {
    if (mb_nr&0x01)
    {
      topMB= &img->mb_data[mb_nr-1];
      if(!(img->type == B_SLICE))
        prevMbSkipped = (topMB->mb_type == 0);
      else
        prevMbSkipped = topMB->skip_flag;
    }
    else
      prevMbSkipped = 0;
  }

  currMB->mb_field = ((mb_nr&0x01) == 0)? 0 : img->mb_data[mb_nr-1].mb_field;

  update_qp(img, currMB, img->qp);
  currSE.type = SE_MBTYPE;

  //  read MB mode *****************************************************************
  dP = &(currSlice->partArr[partMap[currSE.type]]);

  if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)   
    currSE.mapping = linfo_ue;

  if(img->type == I_SLICE || img->type == SI_SLICE)
  {
    // read MB aff
    if (img->MbaffFrameFlag && (mb_nr&0x01)==0)
    {
      TRACE_STRING("mb_field_decoding_flag");
      if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
      {
        currSE.len = (int64) 1;
        readSyntaxElement_FLC(&currSE, dP->bitstream);
      }
      else
      {
        currSE.reading = readFieldModeInfo_CABAC;
        dP->readSyntaxElement(&currSE,img,dP);
      }
      currMB->mb_field = currSE.value1;
    }
    
    if(active_pps->entropy_coding_mode_flag  == CABAC)
      CheckAvailabilityOfNeighborsCABAC(currMB);

    //  read MB type
    TRACE_STRING("mb_type");
    currSE.reading = readMB_typeInfo_CABAC;
    dP->readSyntaxElement(&currSE,img,dP);

    currMB->mb_type = currSE.value1;
    if(!dP->bitstream->ei_flag)
      currMB->ei_flag = 0;
  }
  // non I/SI-slice CABAC
  else if (active_pps->entropy_coding_mode_flag == CABAC)
  {
    // read MB skip_flag
    if (img->MbaffFrameFlag && ((mb_nr&0x01) == 0||prevMbSkipped))
      field_flag_inference(currMB);

    CheckAvailabilityOfNeighborsCABAC(currMB);
    TRACE_STRING("mb_skip_flag");
    currSE.reading = readMB_skip_flagInfo_CABAC;
    dP->readSyntaxElement(&currSE,img,dP);

    currMB->mb_type   = currSE.value1;
    currMB->skip_flag = !(currSE.value1);

    if (img->type==B_SLICE)
      currMB->cbp = currSE.value2;

    if (!dP->bitstream->ei_flag)
      currMB->ei_flag = 0;

    if ((img->type == B_SLICE) && currSE.value1 == 0 && currSE.value2 == 0)
      img->cod_counter=0;

    // read MB AFF
    if (img->MbaffFrameFlag)
    {
      check_bottom=read_bottom=read_top=0;
      if ((mb_nr&0x01)==0)
      {
        check_bottom =  currMB->skip_flag;
        read_top = !check_bottom;
      }
      else
      {
        read_bottom = (topMB->skip_flag && (!currMB->skip_flag));
       }

      if (read_bottom || read_top)
      {
        TRACE_STRING("mb_field_decoding_flag");
        currSE.reading = readFieldModeInfo_CABAC;
        dP->readSyntaxElement(&currSE,img,dP);
        currMB->mb_field = currSE.value1;
      }
      if (check_bottom)
        check_next_mb_and_get_field_mode_CABAC(&currSE,img,dP);
    }

    CheckAvailabilityOfNeighborsCABAC(currMB);

    // read MB type
    if (currMB->mb_type != 0 )
    {
      currSE.reading = readMB_typeInfo_CABAC;
      TRACE_STRING("mb_type");
      dP->readSyntaxElement(&currSE,img,dP);

⌨️ 快捷键说明

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