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

📄 macroblock.c

📁 H.264基于baseline解码器的C++实现源码
💻 C
📖 第 1 页 / 共 5 页
字号:
static inline void readMBRefPictureIdx (SyntaxElement *currSE, DataPartition *dP, Macroblock *currMB, ImageParameters *img, char  **cur_ref_idx, int list, int step_v0, int step_h0)
{
  static int k, j, j0, i0;
  static char refframe;

  for (j0 = 0; j0 < 4; j0 += step_v0)
  {
    img->subblock_y = j0 << 2;
    for (i0 = 0; i0 < 4; i0 += step_h0)
    {
      img->subblock_x = i0 << 2;
      k = 2 * (j0 >> 1) + (i0 >> 1);

      if ((currMB->b8pdir[k] == list || currMB->b8pdir[k] == BI_PRED) && currMB->b8mode[k] != 0)
      {
        refframe = readRefPictureIdx(currSE, dP, currMB->b8mode[k], list);

        for (j = j0; j < j0 + step_v0; j++)
          memset(&cur_ref_idx[j][img->block_x + i0], refframe, step_h0 * sizeof(char));
      }
    }
  }
}

/*!
 ************************************************************************
 * \brief
 *    Function to read reference picture indice values
 ************************************************************************
 */
static inline void readMBMotionVectors (SyntaxElement *currSE, DataPartition *dP, Macroblock *currMB, ImageParameters *img, int list, int step_h0, int step_v0)
{
  static int i, j, k, i4, j4, ii, jj, kk, i0, j0;
  static short curr_mvd[2], curr_mv[2], pred_mv[2];
  static short (*mvd)[4][2];
  static short ***mv;
  static int mv_mode, step_h, step_v;
  static char cur_ref_idx;
  PicMotionParams *motion = &dec_picture->motion;
  static PixelPos block_a, block_b, block_c, block_d;  // neighbor blocks

  for (j0=0; j0<4; j0+=step_v0)
  {
    for (i0=0; i0<4; i0+=step_h0)
    {       
      kk = 2 * (j0 >> 1) + (i0 >> 1);
      if ((currMB->b8pdir[kk]== list || currMB->b8pdir[kk]== BI_PRED) && (currMB->b8mode[kk] !=0))//has forward vector
      {
        cur_ref_idx = motion->ref_idx[list][img->block_y+j0][img->block_x+i0];
        mv_mode  = currMB->b8mode[kk];
        step_h = BLOCK_STEP [mv_mode][0];
        step_v = BLOCK_STEP [mv_mode][1];

        for (j = j0; j < j0 + step_v0; j += step_v)
        {
          img->subblock_y = j << 2; // position used for context determination
          j4 = img->block_y + j;
          mv  = &motion->mv [list][j4];
          mvd = &currMB->mvd     [list][j];
          for (i = i0; i < i0 + step_h0; i += step_h)
          {
            img->subblock_x = i << 2; // position used for context determination
            i4 = img->block_x + i;

            get_neighbors(currMB, &block_a, &block_b, &block_c, &block_d, BLOCK_SIZE * i, BLOCK_SIZE * j, 4 * step_h);

            // first make mv-prediction
            GetMotionVectorPredictor (currMB, &block_a, &block_b, &block_c, pred_mv, cur_ref_idx, motion->ref_idx[list], motion->mv[list], BLOCK_SIZE * i, BLOCK_SIZE * j, 4*step_h, 4*step_v);

            for (k=0; k < 2; k++)
            {
#if TRACE
              static char tstring[20];   
              sprintf( tstring, "mvd_l%d", list); 
              strncpy(currSE->tracestring, tstring, TRACESTRING_SIZE);
#endif
              currSE->value2   = (k << 1) + list; // identifies the component; only used for context determination
              dP->readSyntaxElement(currSE,img,dP);
              curr_mvd[k] = (short) currSE->value1;
              curr_mv [k] = (short)(curr_mvd[k] + pred_mv[k]);  // compute motion vector 
            }

            // Init first line (mv)
            for(ii = i4; ii < i4 + step_h; ii++)
            {
              memcpy(&mv[0][ii][0], curr_mv,  2 * sizeof(short));
            }              
            // now copy all other lines
            for(jj = 1; jj < step_v; jj++)
            {
              memcpy(&mv[jj][i4][0], &mv[0][i4][0],  2 * step_h * sizeof(short));
            }

            // Init first line (mvd)
            for(ii = i; ii < i + step_h; ii++)
            {
              memcpy(&mvd[0][ii][0], curr_mvd,  2 * sizeof(short));
            }              

            // now copy all other lines
            for(jj = 1; jj < step_v; jj++)
            {
              memcpy(&mvd[jj][i][0], &mvd[0][i][0],  2 * step_h * sizeof(short));
            }
          }
        }
      }
    }
  }
}

void invScaleCoeff(ImageParameters *img, Macroblock *currMB, int level, int run, int qp_per, int i, int j, int i0, int j0, int coef_ctr, const byte (*pos_scan4x4)[2], int (*InvLevelScale4x4)[4])
{
  if (level != 0)    /* leave if level == 0 */
  {
    coef_ctr += run + 1;

    i0=pos_scan4x4[coef_ctr][0];
    j0=pos_scan4x4[coef_ctr][1];

    currMB->cbp_blk[0] |= (int64)1 << ((j << 2) + i) ;
    img->cof[0][(j<<2) + j0][(i<<2) + i0]= rshift_rnd_sf((level * InvLevelScale4x4[j0][i0]) << qp_per, 4);
  }
}

/*!
 ************************************************************************
 * \brief
 *    initializes the current macroblock
 ************************************************************************
 */
void start_macroblock(ImageParameters *img, Macroblock **currMB)
{
  int mb_nr = img->current_mb_nr;
  *currMB = &img->mb_data[mb_nr];   // intialization code deleted, see below, StW  
  
  (*currMB)->mbAddrX = mb_nr;

  //assert (mb_nr < (int) img->PicSizeInMbs);

  /* Update coordinates of the current macroblock */
  if (img->MbaffFrameFlag)
  {
    img->mb_x =    (mb_nr) % ((2*img->width) / MB_BLOCK_SIZE);
    img->mb_y = 2*((mb_nr) / ((2*img->width) / MB_BLOCK_SIZE));

    img->mb_y += (img->mb_x & 0x01);
    img->mb_x >>= 1;
  }
  else
  {
    img->mb_x = PicPos[mb_nr][0];
    img->mb_y = PicPos[mb_nr][1];
  }

  /* Define vertical positions */
  img->block_y = img->mb_y * BLOCK_SIZE;      /* luma block position */
  img->block_y_aff = img->block_y;
  img->pix_y   = img->mb_y * MB_BLOCK_SIZE;   /* luma macroblock position */
  img->pix_c_y = img->mb_y * img->mb_cr_size_y; /* chroma macroblock position */

  /* Define horizontal positions */
  img->block_x = img->mb_x * BLOCK_SIZE;      /* luma block position */
  img->pix_x   = img->mb_x * MB_BLOCK_SIZE;   /* luma pixel position */
  img->pix_c_x = img->mb_x * img->mb_cr_size_x; /* chroma pixel position */

  // Save the slice number of this macroblock. When the macroblock below
  // is coded it will use this to decide if prediction for above is possible
  (*currMB)->slice_nr = img->current_slice_nr;

  if (img->current_slice_nr >= MAX_NUM_SLICES)
  {
    error ("Maximum number of supported slices exceeded. \nPlease recompile with increased value for MAX_NUM_SLICES", 200);
  }

  dec_picture->slice_id[img->mb_y][img->mb_x] = (short) img->current_slice_nr;
  dec_picture->max_slice_id = (short) imax(img->current_slice_nr, dec_picture->max_slice_id);

  CheckAvailabilityOfNeighbors(*currMB);

  // Reset syntax element entries in MB struct
   update_qp(img, *currMB, img->qp);
  (*currMB)->mb_type         = 0;
  (*currMB)->delta_quant     = 0;
  (*currMB)->cbp             = 0;  
  memset((*currMB)->cbp_blk, 0, 3 * sizeof(int64));  
  (*currMB)->c_ipred_mode    = DC_PRED_8; //GB

  memset(&((*currMB)->mvd[0][0][0][0]),0, 2 * BLOCK_MULTIPLE * BLOCK_MULTIPLE * 2 * sizeof(short));
  
  memset((*currMB)->cbp_bits, 0, 3 * sizeof(int64));
  memset((*currMB)->cbp_bits_8x8, 0, 3 * sizeof(int64));

  // initialize img->mb_rres
  memset(&(img->mb_rres[0][0][0]), 0, 3 * MB_PIXELS * sizeof(int));

  // store filtering parameters for this MB
  (*currMB)->DFDisableIdc = img->currentSlice->DFDisableIdc;
  (*currMB)->DFAlphaC0Offset = img->currentSlice->DFAlphaC0Offset;
  (*currMB)->DFBetaOffset = img->currentSlice->DFBetaOffset;
}

/*!
 ************************************************************************
 * \brief
 *    set coordinates of the next macroblock
 *    check end_of_slice condition
 ************************************************************************
 */
Boolean exit_macroblock(ImageParameters *img,int eos_bit)
{
 //! The if() statement below resembles the original code, which tested
  //! img->current_mb_nr == img->PicSizeInMbs.  Both is, of course, nonsense
  //! In an error prone environment, one can only be sure to have a new
  //! picture by checking the tr of the next slice header!

// printf ("exit_macroblock: FmoGetLastMBOfPicture %d, img->current_mb_nr %d\n", FmoGetLastMBOfPicture(), img->current_mb_nr);
  img->num_dec_mb++;

  if (img->num_dec_mb == img->PicSizeInMbs)
  {
    return TRUE;
  }
  // ask for last mb in the slice  UVLC
  else
  {

    img->current_mb_nr = FmoGetNextMBNr (img->current_mb_nr);

    if (img->current_mb_nr == -1)     // End of Slice group, MUST be end of slice
    {
      assert (nal_startcode_follows (img->currentSlice, eos_bit) == TRUE);
      return TRUE;
    }

    if(nal_startcode_follows(img->currentSlice, eos_bit) == FALSE)
      return FALSE;

    if(img->type == I_SLICE  || img->type == SI_SLICE || active_pps->entropy_coding_mode_flag == CABAC)
      return TRUE;
    if(img->cod_counter <= 0)
      return TRUE;
    return FALSE;
  }
}

/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for P-Frames
 ************************************************************************
 */
static void interpret_mb_mode_P(Macroblock *currMB)
{
  const int ICBPTAB[6] = {0,16,32,15,31,47};
  int         mbmode = currMB->mb_type;

#define ZERO_P8x8     (mbmode==5)
#define MODE_IS_P8x8  (mbmode==4 || mbmode==5)
#define MODE_IS_I4x4  (mbmode==6)
#define I16OFFSET     (mbmode-7)
#define MODE_IS_IPCM  (mbmode==31)

  if(mbmode <4)
  {
    currMB->mb_type = mbmode;
    memset(&currMB->b8mode[0],mbmode,4 * sizeof(char));
    memset(&currMB->b8pdir[0], 0, 4 * sizeof(char));
  }
  else if(MODE_IS_P8x8)
  {
    currMB->mb_type = P8x8;
    img->allrefzero = ZERO_P8x8;
  }
  else if(MODE_IS_I4x4)
  {
    currMB->mb_type = I4MB;
    memset(&currMB->b8mode[0],IBLOCK, 4 * sizeof(char));
    memset(&currMB->b8pdir[0],    -1, 4 * sizeof(char));
  }
  else if(MODE_IS_IPCM)
  {
    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[(I16OFFSET)>>2];
    currMB->i16mode = (I16OFFSET) & 0x03;
    memset(&currMB->b8mode[0], 0, 4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1, 4 * sizeof(char));
  }
}

/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for I-Frames
 ************************************************************************
 */
static void interpret_mb_mode_I(Macroblock *currMB)
{
  static const int ICBPTAB[6] = {0,16,32,15,31,47};
  int         mbmode   = currMB->mb_type;

  if (mbmode==0)
  {
    currMB->mb_type = I4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else if(mbmode==25)
  {
    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-1) & 0x03;
    memset(&currMB->b8mode[0], 0, 4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1, 4 * sizeof(char));
  }
}

/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for B-Frames
 ************************************************************************
 */
static void interpret_mb_mode_B(Macroblock *currMB)
{
  static const int offset2pdir16x16[12]   = {0, 0, 1, 2, 0,0,0,0,0,0,0,0};
  static const int offset2pdir16x8[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0},{1,0},
                                             {0,0},{0,2},{0,0},{1,2},{0,0},{2,0},{0,0},{2,1},{0,0},{2,2},{0,0}};
  static const int offset2pdir8x16[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0},
                                             {1,0},{0,0},{0,2},{0,0},{1,2},{0,0},{2,0},{0,0},{2,1},{0,0},{2,2}};

  const int ICBPTAB[6] = {0,16,32,15,31,47};

  int i, mbmode;
  int mbtype  = currMB->mb_type;

  //--- set mbtype, b8type, and b8pdir ---
  if (mbtype==0)       // direct
  {
    mbmode=0;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],2,4 * sizeof(char));
  }
  else if (mbtype==23) // intra4x4
  {
    mbmode=I4MB;
    memset(&currMB->b8mode[0],IBLOCK,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));
  }
  else if ((mbtype>23) && (mbtype<48) ) // intra16x16
  {
    mbmode=I16MB;
    memset(&currMB->b8mode[0],0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));

    currMB->cbp     = ICBPTAB[(mbtype-24)>>2];
    currMB->i16mode = (mbtype-24) & 0x03;
  }
  else if (mbtype==22) // 8x8(+split)
  {
    mbmode=P8x8;       // b8mode and pdir is transmitted in additional codewords
  }
  else if (mbtype<4)   // 16x16
  {
    mbmode=1;
    memset(&currMB->b8mode[0], 1,4 * sizeof(char));
    memset(&currMB->b8pdir[0],offset2pdir16x16[mbtype],4 * sizeof(char));
  }
  else if(mbtype==48)
  {
    mbmode=IPCM;
    memset(&currMB->b8mode[0], 0,4 * sizeof(char));
    memset(&currMB->b8pdir[0],-1,4 * sizeof(char));

    currMB->cbp= -1;
    currMB->i16mode = 0;
  }

  else if ((mbtype&0x01)==0) // 16x8
  {
    mbmode=2;
    memset(&currMB->b8mode[0], 2,4 * sizeof(char));
    for(i=0;i<4;i++)
    {
      currMB->b8pdir[i] = (char) offset2pdir16x8 [mbtype][i>>1];
    }
  }
  else
  {
    mbmode=3;
    memset(&currMB->b8mode[0], 3,4 * sizeof(char));
    for(i=0;i<4;i++)
    {
      currMB->b8pdir[i] = (char) offset2pdir8x16 [mbtype][i&0x01];
    }
  }
  currMB->mb_type = mbmode;
}
/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for SI-Frames

⌨️ 快捷键说明

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