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

📄 macroblock.c

📁 h.264/avc 视频编码程序,实现分数像素匹配功能,非原创.
💻 C
📖 第 1 页 / 共 5 页
字号:
      {
        refFrArr[img->block_y+j][img->block_x+i] = refframe;
      }
  }
  else
  {
    for (j=0; j<4; j++)
    for (i=0; i<4; i++)
    {
      fw_refFrArr[img->block_y+j][img->block_x+i] = refframe;
      bw_refFrArr[img->block_y+j][img->block_x+i] = bwrefframe;
    }
  }
}




/*!
 ************************************************************************
 * \brief
 *    Check if all reference frames for a macroblock are zero
 ************************************************************************
 */
int
ZeroRef (Macroblock* currMB)
{
  int i,j;
  for (j=0; j<4; j++)
  for (i=0; i<4; i++)
  {
    if (currMB->b8mode[2*(j/2)+(i/2)]!=IBLOCK && refFrArr[img->block_y+j][img->block_x+i]!=0)
    {
        return 0;
    }
  }
  return 1;
}


/*!
 ************************************************************************
 * \brief
 *    Converts macroblock type to coding value
 ************************************************************************
 */
int
MBType2Value (Macroblock* currMB)
{
  static const int dir1offset[3]    =  { 1,  2, 3};
  static const int dir2offset[3][3] = {{ 0,  4,  8},   // 1. block forward
                                       { 6,  2, 10},   // 1. block backward
                                       {12, 14, 16}};  // 1. block bi-directional

  int mbtype, pdir0, pdir1;

  if (img->type!=B_IMG)
  {
    if      (currMB->mb_type==I4MB)     return (img->type==INTRA_IMG ? 0 : 6);
    else if (currMB->mb_type==I16MB)    return (img->type==INTRA_IMG ? 0 : 6) + img->i16offset;
    else if (currMB->mb_type==P8x8)
    {
      if (input->symbol_mode==UVLC && ZeroRef (currMB))  return 5;
      else                                               return 4;
    }
    else                                return currMB->mb_type;
  }
  else
  {
    mbtype = currMB->mb_type;
    pdir0  = currMB->b8pdir[0];
    pdir1  = currMB->b8pdir[3];

    if      (mbtype==0)       return 0;
    else if (mbtype==I4MB)    return 23;
    else if (mbtype==I16MB)   return 23 + img->i16offset;
    else if (mbtype==P8x8)    return 22;
    else if (mbtype==1)       return dir1offset[pdir0];
    else if (mbtype==2)       return 4 + dir2offset[pdir0][pdir1];
    else                      return 5 + dir2offset[pdir0][pdir1];
  }
}



/*!
 ************************************************************************
 * \brief
 *    Writes intra prediction modes for an 8x8 block
 ************************************************************************
 */
int
writeIntra4x4Modes (int block8x8)
{
  int i, i0=4*block8x8, i1=i0+4;
  int           rate        = 0;
  Macroblock    *currMB     = &img->mb_data[img->current_mb_nr];
  SyntaxElement *currSE    = &img->MB_SyntaxElements[currMB->currSEnr];
  int           *bitCount   = currMB->bitcounter;
  Slice         *currSlice  = img->currentSlice;
  DataPartition *dataPart;
  const int     *partMap    = assignSE2partition[input->partition_mode];

  for (i=i0; i<i1; )
  {
    currSE->context = i;
    currSE->value1  = currMB->intra_pred_modes[i++];
    currSE->value2  = currMB->intra_pred_modes[i++];

#if TRACE
    snprintf(currSE->tracestring, TRACESTRING_SIZE, "Intra mode     = %3d",IPRED_ORDER[currSE->value1][currSE->value2]);
#endif

    /*--- set symbol type and function pointers ---*/
    if (input->symbol_mode == UVLC)    currSE->mapping = intrapred_linfo;
    else                               currSE->writing = writeIntraPredMode2Buffer_CABAC;
    currSE->type = SE_INTRAPREDMODE;
      
    /*--- choose data partition ---*/
    if (img->type==B_IMG)   dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);
    else                    dataPart = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);
    
    /*--- encode and update rate ---*/
    dataPart->writeSyntaxElement (currSE, dataPart);
    bitCount[BITS_COEFF_Y_MB]+=currSE->len;
    rate += currSE->len;
    currSE++;
    currMB->currSEnr++;
  }
  return rate;
}



/*!
 ************************************************************************
 * \brief
 *    Converts 8x8 block tyoe to coding value
 ************************************************************************
 */
int
B8Mode2Value (int b8mode, int b8pdir)
{
  static const int b8start[8] = {0,0,0,0, 1, 4, 5, 10};
  static const int b8inc  [8] = {0,0,0,0, 1, 2, 2, 1};

  if (img->type!=B_IMG)
  {
    return (b8mode==IBLOCK?4:b8mode-4);
  }
  else
  {
    if (b8mode==IBLOCK)  return 13;
    else                 return b8start[b8mode] + b8inc[b8mode] * b8pdir;
  }
}



/*!
 ************************************************************************
 * \brief
 *    Codes macroblock header
 ************************************************************************
 */
int
writeMBHeader ()
{
  int             i;
  int             mb_nr     = img->current_mb_nr;
  Macroblock*     currMB    = &img->mb_data[mb_nr];
  SyntaxElement *currSE    = &img->MB_SyntaxElements[currMB->currSEnr];
  int*            bitCount  = currMB->bitcounter;
  Slice*          currSlice = img->currentSlice;
  DataPartition*  dataPart;
  const int*      partMap   = assignSE2partition[input->partition_mode];
  int             no_bits   = 0;


  // choose the appropriate data partition
  if (img->type == B_IMG)   dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);
  else                      dataPart = &(currSlice->partArr[partMap[SE_MBTYPE]]);


  //=====  BITS FOR MACROBLOCK MODE =====
  if(img->type == INTRA_IMG || img->types == SP_IMG || input->symbol_mode == CABAC)
  {
    //===== No Run Length Coding of SKIP modes =====
    currSE->value1  = MBType2Value (currMB);
    currSE->type    = SE_MBTYPE;

    if (input->symbol_mode == UVLC)  currSE->mapping = n_linfo2;
    else                             currSE->writing = writeMB_typeInfo2Buffer_CABAC;

    dataPart->writeSyntaxElement( currSE, dataPart);
#if TRACE
    if (img->type == B_IMG)  snprintf(currSE->tracestring, TRACESTRING_SIZE, "B_MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y, currMB->mb_type);
    else                     snprintf(currSE->tracestring, TRACESTRING_SIZE,   "MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y,currMB->mb_type);
#endif
    bitCount[BITS_MB_MODE] += currSE->len;
    no_bits                += currSE->len;
    currSE++;
    currMB->currSEnr++;
  }
  else if (currMB->mb_type != 0 || (img->type == B_IMG && currMB->cbp != 0))
  {
    //===== Run Length Coding: Non-Skipped macorblock =====
    currSE->value1  = img->cod_counter;
    currSE->mapping = n_linfo2;
    currSE->type    = SE_MBTYPE;
    dataPart->writeSyntaxElement( currSE, dataPart);
#if TRACE
    snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB runlength = %3d",img->cod_counter);
#endif
    bitCount[BITS_MB_MODE] += currSE->len;
    no_bits                += currSE->len;
    currSE++;
    currMB->currSEnr++;
    
    // Reset cod counter
    img->cod_counter = 0;

    // Put out mb mode
    currSE->value1  = MBType2Value (currMB);
    if(img->type != B_IMG)
    {
      currSE->value1--;
    }
    currSE->mapping = n_linfo2;
    currSE->type    = SE_MBTYPE;

    dataPart->writeSyntaxElement( currSE, dataPart);
#if TRACE
    if (img->type == B_IMG)   snprintf(currSE->tracestring, TRACESTRING_SIZE, "B_MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y, currMB->mb_type);
    else                      snprintf(currSE->tracestring, TRACESTRING_SIZE,   "MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y,currMB->mb_type);
#endif
    bitCount[BITS_MB_MODE] += currSE->len;
    no_bits                += currSE->len;
    currSE++;
    currMB->currSEnr++;
  }
  else
  {
    //Run Length Coding: Skipped macroblock
    img->cod_counter++;

    if(img->current_mb_nr == img->total_number_mb)
    {
      // Put out run
      currSE->value1  = img->cod_counter;
      currSE->mapping = n_linfo2;
      currSE->type    = SE_MBTYPE;

      dataPart->writeSyntaxElement( currSE, dataPart);
#if TRACE
      snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB runlength = %3d",img->cod_counter);
#endif
      bitCount[BITS_MB_MODE] += currSE->len;
      no_bits                += currSE->len;
      currSE++;
      currMB->currSEnr++;

      // Reset cod counter
      img->cod_counter = 0;
    }
  }


  //===== BITS FOR 8x8 SUB-PARTITION MODI =====
  if (IS_P8x8 (currMB))
  {
    if (img->type==B_IMG) dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);
    else                  dataPart = &(currSlice->partArr[partMap[SE_MBTYPE]]);

    for (i=0; i<4; i++)
    {
      if (input->symbol_mode==UVLC)   currSE->mapping = n_linfo2;
      else                            currSE->writing = writeB8_typeInfo2Buffer_CABAC;

      currSE->value1  = B8Mode2Value (currMB->b8mode[i], currMB->b8pdir[i]);
      currSE->type    = SE_MBTYPE;
      dataPart->writeSyntaxElement (currSE, dataPart);
      bitCount[BITS_MB_MODE]+= currSE->len;
      no_bits               += currSE->len;
      currSE++;
      currMB->currSEnr++;
    }
  }


  //===== BITS FOR INTRA PREDICTION MODI ====
  for (i=0; i<4; i++)
  {
    if (currMB->b8mode[i]==IBLOCK)
    {
      no_bits += writeIntra4x4Modes (i);
    }
  }

  return no_bits;
}



/*!
 ************************************************************************
 * \brief
 *    Passes the chosen syntax elements to the NAL
 ************************************************************************
 */
void write_one_macroblock ()
{
  Macroblock* currMB   = &img->mb_data[img->current_mb_nr];
  int*        bitCount = currMB->bitcounter;

  //--- write header ---
  writeMBHeader ();

  //  Do nothing more if copy and inter mode
  if ((IS_INTERMV (currMB)  || IS_INTRA (currMB)                             ) ||
      (img->type==B_IMG     && input->symbol_mode== CABAC                    ) ||
      (img->type==B_IMG     && input->symbol_mode== UVLC &&  currMB->cbp != 0)  )
  {
    writeMotionInfo2NAL  ();
    writeCBPandLumaCoeff ();
    writeChromaCoeff     ();
  }

  //--- constrain intra prediction ---
  if(input->UseConstrainedIntraPred && img->type==INTER_IMG && img->types != SP_IMG)
  {
    if (!IS_NEWINTRA (currMB) && currMB->b8mode[0]!=IBLOCK) img->intra_block[img->current_mb_nr][0] = 0;
    if (!IS_NEWINTRA (currMB) && currMB->b8mode[1]!=IBLOCK) img->intra_block[img->current_mb_nr][1] = 0;
    if (!IS_NEWINTRA (currMB) && currMB->b8mode[2]!=IBLOCK) img->intra_block[img->current_mb_nr][2] = 0;
    if (!IS_NEWINTRA (currMB) && currMB->b8mode[3]!=IBLOCK) img->intra_block[img->current_mb_nr][3] = 0;
  }

  //--- set total bit-counter ---
  bitCount[BITS_TOTAL_MB] = bitCount[BITS_MB_MODE] + bitCount[BITS_COEFF_Y_MB]     + bitCount[BITS_INTER_MB]
                          + bitCount[BITS_CBP_MB]  + bitCount[BITS_DELTA_QUANT_MB] + bitCount[BITS_COEFF_UV_MB];
  stat->bit_slice += bitCount[BITS_TOTAL_MB];
}




/*!
 ************************************************************************
 * \brief
 *    Sets context for reference frame parameter
 ************************************************************************
 */
int
BType2CtxRef (int btype)
{
  if (btype<4)   return 0;
  else           return 1;
}


/*!
 ************************************************************************
 * \brief
 *    Codes the reference frame
 ************************************************************************
 */
int
writeReferenceFrame (int  mode,
                     int  i,
                     int  j,
                     int  ref)
{
  Macroblock*     currMB    = &img->mb_data[img->current_mb_nr];
  SyntaxElement*  currSE    = &img->MB_SyntaxElements[currMB->currSEnr];
  Slice*          currSlice = img->currentSlice;
  int*            bitCount  = currMB->bitcounter;
  const int*      partMap   = assignSE2partition[input->partition_mode];
  int             rate      = 0;
  DataPartition*  dataPart;


  currSE->value1 = ref;
  currSE->type   = (img->type==B_IMG ? SE_BFRAME : SE_REFFRAME);

⌨️ 快捷键说明

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