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

📄 macroblock.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 5 页
字号:
              for (i=0;i<4;i++)
              {
                i2 = ii4+i*4;
                img->mpr[i+block_x][j+block_y]=UMVPelY_14 (mref[img->multframe_no], j2, i2);

              }
            }
          }

          for (j=0; j < BLOCK_SIZE; j++)
          {
            for (i=0; i < BLOCK_SIZE; i++)
            {
              img->m7[i][j] =imgY_org[img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr[i+block_x][j+block_y];
            }
          }
          if (img->types!=SP_IMG)
            nonzero=dct_luma(block_x,block_y,&coeff_cost);
          else nonzero=dct_luma_sp(block_x,block_y,&coeff_cost);

          if (nonzero)
          {
            currMB->cbp_blk |= 1 << cbp_blk_mask ;            // one bit for every 4x4 block
            currMB->cbp     |= cbp_mask;       // one bit for the 4x4 blocks of an 8x8 block
          }
        }
      }

      /*
      The purpose of the action below is to prevent that single or 'expensive' coefficients are coded.
      With 4x4 transform there is larger chance that a single coefficient in a 8x8 or 16x16 block may be nonzero.
      A single small (level=1) coefficient in a 8x8 block will cost: 3 or more bits for the coefficient,
      4 bits for EOBs for the 4x4 blocks,possibly also more bits for CBP.  Hence the total 'cost' of that single
      coefficient will typically be 10-12 bits which in a RD consideration is too much to justify the distortion improvement.
      The action below is to watch such 'single' coefficients and set the reconstructed block equal to the prediction according
      to a given criterium.  The action is taken only for inter luma blocks.

        Notice that this is a pure encoder issue and hence does not have any implication on the standard.
        coeff_cost is a parameter set in dct_luma() and accumulated for each 8x8 block.  If level=1 for a coefficient,
        coeff_cost is increased by a number depending on RUN for that coefficient.The numbers are (see also dct_luma()): 3,2,2,1,1,1,0,0,...
        when RUN equals 0,1,2,3,4,5,6, etc.
        If level >1 coeff_cost is increased by 9 (or any number above 3). The threshold is set to 3. This means for example:
        1: If there is one coefficient with (RUN,level)=(0,1) in a 8x8 block this coefficient is discarded.
        2: If there are two coefficients with (RUN,level)=(1,1) and (4,1) the coefficients are also discarded
        sum_cnt_nonz is the accumulation of coeff_cost over a whole macro block.  If sum_cnt_nonz is 5 or less for the whole MB,
        all nonzero coefficients are discarded for the MB and the reconstructed block is set equal to the prediction.
      */

      if (coeff_cost > 3)
      {
        sum_cnt_nonz += coeff_cost;
      }
      else //discard
      {
        currMB->cbp     &=  (63  -  cbp_mask ) ;
        currMB->cbp_blk &= ~(51 << (mb_y + (mb_x>>2) )) ;
        for (i=mb_x; i < mb_x+BLOCK_SIZE*2; i++)
        {
          for (j=mb_y; j < mb_y+BLOCK_SIZE*2; j++)
          {
            imgY[img->pix_y+j][img->pix_x+i]=img->mpr[i][j];
          }
        }
        if (img->types==SP_IMG)
          for (i=mb_x; i < mb_x+BLOCK_SIZE*2; i+=BLOCK_SIZE)
            for (j=mb_y; j < mb_y+BLOCK_SIZE*2; j+=BLOCK_SIZE)
              copyblock_sp(i,j);
      }
    }
  }

  if (sum_cnt_nonz <= 5 )
  {
     currMB->cbp     &= 0xfffff0 ;
     currMB->cbp_blk &= 0xff0000 ;
     for (i=0; i < MB_BLOCK_SIZE; i++)
     {
       for (j=0; j < MB_BLOCK_SIZE; j++)
       {
         imgY[img->pix_y+j][img->pix_x+i]=img->mpr[i][j];
       }
     }
     if (img->types==SP_IMG)
       for (i=0; i < MB_BLOCK_SIZE; i+=BLOCK_SIZE)
         for (j=0; j < MB_BLOCK_SIZE; j+=BLOCK_SIZE)
           copyblock_sp(i,j);
   }
}

/*!
 ************************************************************************
 * \brief
 *    Performs DCT, quantization, run/level pre-coding and IDCT
 *    for the chrominance of a I- of P-frame macroblock;
 *    current cbp and cr_cbp are affected
 ************************************************************************
 */
void ChromaCoding_P(int *cr_cbp)
{
  int i, j;
  int uv, ii,jj,ii0,jj0,ii1,jj1,if1,jf1,if0,jf0,f1,f2,f3,f4;
  int pic_block_y, pic_block_x;
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];

  if(input->mv_res)
  {
    f1=16;
    f2=15;
  }
  else
  {
    f1=8;
    f2=7;
  }

  f3=f1*f1;
  f4=f3/2;

  *cr_cbp=0;
  for (uv=0; uv < 2; uv++)
  {
    if (img->imod == INTRA_MB_OLD || img->imod == INTRA_MB_NEW)
    {
      intrapred_chroma(img->pix_c_x,img->pix_c_y,uv);
    }
    else
    {
      for (j=0; j < MB_BLOCK_SIZE/2; j++)
      {
        pic_block_y=(img->pix_c_y+j)/2;
        for (i=0; i < MB_BLOCK_SIZE/2; i++)
        {
          pic_block_x=(img->pix_c_x+i)/2;
          ii=(img->pix_c_x+i)*f1+tmp_mv[0][pic_block_y][pic_block_x+4];
          jj=(img->pix_c_y+j)*f1+tmp_mv[1][pic_block_y][pic_block_x+4];

          ii0 = max (0, min (img->width_cr-1,ii/f1));
          jj0 = max (0, min (img->height_cr-1,jj/f1));
          ii1 = max (0, min (img->width_cr-1,(ii+f2)/f1));
          jj1 = max (0, min (img->height_cr-1,(jj+f2)/f1));

          if1=(ii & f2);
          jf1=(jj & f2);
          if0=f1-if1;
          jf0=f1-jf1;
          img->mpr[i][j]=(if0*jf0*mcef[img->multframe_no][uv][jj0][ii0]+
            if1*jf0*mcef[img->multframe_no][uv][jj0][ii1]+
            if0*jf1*mcef[img->multframe_no][uv][jj1][ii0]+
            if1*jf1*mcef[img->multframe_no][uv][jj1][ii1]+f4)/f3;

          img->m7[i][j]=imgUV_org[uv][img->pix_c_y+j][img->pix_c_x+i]-img->mpr[i][j];
        }
      }
    }
    if (img->types!=SP_IMG || (img->imod == INTRA_MB_OLD || img->imod == INTRA_MB_NEW) )
      *cr_cbp=dct_chroma(uv,*cr_cbp);
    else *cr_cbp=dct_chroma_sp(uv,*cr_cbp);
  }
  currMB->cbp += *cr_cbp*16;
}

/*!
 ************************************************************************
 * \brief
 *    Set reference frame information in global arrays
 *    depending on mode decision. Used for motion vector prediction.
 ************************************************************************
 */
void SetRefFrameInfo_P()
{
  int i,j;

  if (img->imod == INTRA_MB_OLD || img->imod == INTRA_MB_NEW)
  {
    // Set the reference frame information for motion vector prediction as unavailable
    for (j = 0;j < BLOCK_MULTIPLE;j++)
    {
      for (i = 0;i < BLOCK_MULTIPLE;i++)
      {
        refFrArr[img->block_y+j][img->block_x+i] = -1;
      }
    }
  }
  else
  {
    // Set the reference frame information for motion vector prediction
    for (j = 0;j < BLOCK_MULTIPLE;j++)
    {
      for (i = 0;i < BLOCK_MULTIPLE;i++)
      {
        refFrArr[img->block_y+j][img->block_x+i] =  img->mb_data[img->current_mb_nr].ref_frame;
      }
    }
  }
}


/*!
 ************************************************************************
 * \brief
 *    Encode one macroblock depending on chosen picture type
 ************************************************************************
 */
void encode_one_macroblock()
{
  int cr_cbp;             // chroma coded block pattern
  int tot_intra_sad;
  int intra_pred_mode_2;  // best 16x16 intra mode

  if (input->rdopt)
  {
    RD_Mode_Decision ();
  }
  else
  {
    Macroblock *currMB = &img->mb_data[img->current_mb_nr];

    tot_intra_sad = MakeIntraPrediction(&intra_pred_mode_2);     // Intra Prediction
    if (img->type != B_IMG)         // I- or P-frame
    {
      if ((img->mb_y == img->mb_y_upd && img->mb_y_upd != img->mb_y_intra) || img->type == INTRA_IMG)
      {
        img->mb_mode=8*img->type+img->imod;  // Intra mode: set if intra image or if intra GOB for error robustness
      }
      else
      {
        currMB->ref_frame = motion_search(tot_intra_sad);      // P-frames MV-search
      }
    }
    else                          // B-frame
      currMB->ref_frame = motion_search_Bframe(tot_intra_sad); // B-frames MV-search

    if (img->type == B_IMG)         // B-frame
    {

      LumaResidualCoding_B(img);           // Residual coding of Luma (B-modes only)
      ChromaCoding_B(&cr_cbp);                              // Coding of Chrominance


      SetRefFrameInfo_B();     // Set ref-frame info for mv-prediction of future MBs
    }
    else                  // I- or P-frame
    {
      if (currMB->intraOrInter == INTER_MB)
        LumaResidualCoding_P();    // Residual coding of Luma (only for inter modes)
      // Coding of Luma in intra mode is done implicitly in MakeIntraPredicition
      ChromaCoding_P(&cr_cbp);                              // Coding of Chrominance

      // Set reference frame information for motion vector prediction of future MBs
      SetRefFrameInfo_P();

      //  Check if a MB is skipped (no coeffs. only 0-vectors and prediction from the most recent frame)
      if(   (currMB->ref_frame                      == 0) && (currMB->intraOrInter == INTER_MB)
        && (tmp_mv[0][img->block_y][img->block_x+4]== 0) && (img->mb_mode         == M16x16_MB)
        && (tmp_mv[1][img->block_y][img->block_x+4]== 0) && (currMB->cbp          == 0) )
        img->mb_mode=COPY_MB;
    }

    currMB->qp = img->qp; // this should (or has to be) done somewere else. where?
    DeblockMb(img, imgY, imgUV) ; // Deblock this MB ( pixels to the right and above are affected)

    if (img->imod==INTRA_MB_NEW)        // Set 16x16 intra mode and make "intra CBP"
    {
      img->mb_mode += intra_pred_mode_2 + 4*cr_cbp + 12*img->kac;
      currMB->cbp += 15*img->kac; //GB
    }


    if ((((img->type == INTER_IMG)||(img->types==SP_IMG))  && ((img->imod==INTRA_MB_NEW) || (img->imod==INTRA_MB_OLD)))
      || (img->type == B_IMG && (img->imod==B_Backward || img->imod==B_Direct || img->imod==INTRA_MB_NEW || img->imod==INTRA_MB_OLD)))// gb b-frames too
      currMB->ref_frame = 0;

  }
}

/*!
 ************************************************************************
 * \brief
 *    Passes the chosen syntax elements to the NAL
 ************************************************************************
 */
void write_one_macroblock()
{
  int i;
  int mb_nr = img->current_mb_nr;
  SyntaxElement *currSE = img->MB_SyntaxElements;
  Macroblock *currMB = &img->mb_data[mb_nr];
  int *bitCount = currMB->bitcounter;
  Slice *currSlice = img->currentSlice;
  DataPartition *dataPart;
  int *partMap = assignSE2partition[input->partition_mode];

  // Store imod for further use
  currMB->mb_imode = img->imod;

  // Store mb_mode for further use
  currMB->mb_type = (currSE->value1 = img->mb_mode);

  // 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 mode
  if(img->type == INTRA_IMG || img->types == SP_IMG || input->symbol_mode == CABAC)
  {
    if (input->symbol_mode == UVLC)
      currSE->mapping = n_linfo2;
    else
      currSE->writing = writeMB_typeInfo2Buffer_CABAC;
    currSE->type = SE_MBTYPE;

#if TRACE
    if (img->type == B_IMG)
      snprintf(currSE->tracestring, TRACESTRING_SIZE, "B_MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y, img->mb_mode);
    else
      snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y,img->mb_mode);
#endif
    dataPart->writeSyntaxElement( currSE, dataPart);

    bitCount[BITS_MB_MODE]+=currSE->len;
    currSE++;
    currMB->currSEnr++;

  }
  else
  {
    if (img->mb_mode != COPY_MB || currMB->intraOrInter != INTER_MB || (img->type == B_IMG && currMB->cbp != 0))
  {
      // Macroblock is coded, put out run and mbmode
      currSE->value1 = img->cod_counter;
      currSE->mapping = n_linfo2;
      currSE->type = SE_MBTYPE;
#if TRACE
      snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB runlength = %3d",img->cod_counter);
#endif
      dataPart->writeSyntaxElement( currSE, dataPart);
      bitCount[BITS_MB_MODE]+=currSE->len;
      currSE++;
      currMB->currSEnr++;
    // Reset cod counter
      img->cod_counter = 0;

      // Put out mb mode
      currSE->value1 = img->mb_mode;
      if(img->type != B_IMG)
        currSE->value1--;
      currSE->mapping = n_linfo2;
      currSE->type = SE_MBTYPE;
#if TRACE
      if (img->type == B_IMG)
        snprintf(currSE->tracestring, TRACESTRING_SIZE, "B_MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y, img->mb_mode);
      else
        snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y,img->mb_mode);
#endif
      dataPart->writeSyntaxElement( currSE, dataPart);
      bitCount[BITS_MB_MODE]+=currSE->len;
      currSE++;
      currMB->currSEnr++;
    }
  else
  {
      // Macroblock is skipped, increase cod_counter
      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;
#if TRACE
        snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB runlength = %3d",img->cod_counter);
#endif
        dataPart->writeSyntaxElement( currSE, dataPart);
        bitCount[BITS_MB_MODE]+=currSE->len;
        currSE++;
        currMB->currSEnr++;

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

  if(input->UseConstrainedIntraPred)
  {
    if (img->type==INTER_IMG && img->types != SP_IMG)
      if(currMB->intraOrInter == INTER_MB)
        img->intra_mb[img->current_mb_nr] = 0;

⌨️ 快捷键说明

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