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

📄 macroblock.cpp

📁 264的播放器
💻 CPP
📖 第 1 页 / 共 4 页
字号:

/*!
 ***********************************************************************
 * \file macroblock.c
 *
 * \brief
 *     Decode a Macroblock
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *    - Inge Lille-Langoy               <inge.lille-langoy@telenor.com>
 *    - Rickard Sjoberg                 <rickard.sjoberg@era.ericsson.se>
 *    - Jani Lainema                    <jani.lainema@nokia.com>
 *    - Sebastian Purreiter             <sebastian.purreiter@mch.siemens.de>
 *    - Thomas Wedi                     <wedi@tnt.uni-hannover.de>
 *    - Detlev Marpe                    <marpe@hhi.de>
 *    - Gabi Blaettermann               <blaetter@hhi.de>
 *    - Ye-Kui Wang                     <wyk@ieee.org>
 ***********************************************************************
*/

#include "contributors.h"

#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#include "global.h"
#include "mbuffer.h"
#include "elements.h"
#include "errorconcealment.h"
#include "macroblock.h"
#include "fmo.h"
#include "vlc.h"
#include "image.h"
#include "mb_access.h"

extern pic_parameter_set_rbsp_t *active_pps;
extern seq_parameter_set_rbsp_t *active_sps;
extern int  (*nal_startcode_follows) (struct img_par *img, int dummy);

static void SetMotionVectorPredictor (struct img_par  *img,
                                      int             *pmv_x,
                                      int             *pmv_y,
                                      int             ref_frame,
                                      int             list,
                                      int             ***refPic,
                                      int             ****tmp_mv,
                                      int             block_x,
                                      int             block_y,
                                      int             blockshape_x,
                                      int             blockshape_y);
/*!
 ************************************************************************
 * \brief
 *    initializes the current macroblock
 ************************************************************************
 */
void start_macroblock(struct img_par *img, int CurrentMBInScanOrder)
{
  Macroblock *currMB;   // intialization code deleted, see below, StW

  assert (img->current_mb_nr >=0 && img->current_mb_nr < img->PicSizeInMbs);

  currMB = &img->mb_data[img->current_mb_nr];

  /* Update coordinates of the current macroblock */
  img->mb_x = (img->current_mb_nr)%(img->width>>4);
  img->mb_y = (img->current_mb_nr)/(img->width>>4);
  
  /* Define vertical positions */
  img->block_y = img->mb_y <<2;      /* luma block position */
  img->pix_y   = img->mb_y <<4;   /* luma macroblock position */
  img->pix_c_y = img->mb_y <<3; /* chroma macroblock position */
  
  /* Define horizontal positions */
  img->block_x = img->mb_x <<2;      /* luma block position */
  img->pix_x   = img->mb_x <<4;   /* luma pixel position */
  img->pix_c_x = img->mb_x <<3; /* 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;
  
  CheckAvailabilityOfNeighbors();

  // Reset syntax element entries in MB struct
  currMB->qp          = img->qp ;
  currMB->mb_type     = 0;
  currMB->delta_quant = 0;
  currMB->cbp         = 0;
  currMB->cbp_blk     = 0;
  currMB->c_ipred_mode= DC_PRED_8; //GB

  memset(currMB->mvd,0,64*sizeof(int));

  // initialize img->m7 for ABT
  memset(img->m7,0,256*sizeof(int));

  // store filtering parameters for this MB 
  currMB->LFDisableIdc = img->currentSlice->LFDisableIdc;
  currMB->LFAlphaC0Offset = img->currentSlice->LFAlphaC0Offset;
  currMB->LFBetaOffset = img->currentSlice->LFBetaOffset;

}

/*!
 ************************************************************************
 * \brief
 *    set coordinates of the next macroblock
 *    check end_of_slice condition 
 ************************************************************************
 */
Boolean exit_macroblock(struct img_par *img,int eos_bit)
{
  Slice *currSlice = img->currentSlice;

  //! 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!

  img->num_dec_mb++;
  
  if (img->num_dec_mb == img->PicSizeInMbs)
  {
    if (currSlice->next_header != EOS)
      currSlice->next_header = SOP;
    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, eos_bit) == TRUE);
      return TRUE;
    }

    if(nal_startcode_follows(img, eos_bit) == FALSE) 
      return FALSE;

    if(img->cod_counter<=0)
      return TRUE;
    return FALSE;
  }
}

/*!
 ************************************************************************
 * \brief
 *    Interpret the mb mode for P-Frames
 ************************************************************************
 */
void interpret_mb_mode_P(struct img_par *img)
{
  int i;
  const int ICBPTAB[6] = {0,16,32,15,31,47};
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
  int         mbmode = currMB->mb_type;
  unsigned int mbmode_case;
  mbmode_case=mbmode<4 ? 1:(mbmode==4? 2:(mbmode==5 ? 3:(mbmode==6? 4:(mbmode==31 ?5:6))));
  switch(mbmode_case)
  {
  case 1:
	currMB->mb_type = mbmode;
    for (i=0;i<4;i++)	{currMB->b8mode[i] = mbmode; currMB->b8pdir[i] = 0;}
	break;
  case 2:
	currMB->mb_type = P8x8;  
    img->allrefzero = 0;
	break;
  case 3:
	currMB->mb_type = P8x8;  
    img->allrefzero = 1;
	break;
  case 4:
	currMB->mb_type = I4MB;
    for (i=0;i<4;i++)	{/*currMB->b8mode[i] = IBLOCK;*/ currMB->b8pdir[i] = -1;}
	break;
  case 5:
	currMB->mb_type=IPCM;    
    for (i=0;i<4;i++)     {currMB->b8mode[i]=0; currMB->b8pdir[i]=-1;}
    currMB->cbp= -1;
    currMB->i16mode = 0;
	break;
  default:
	currMB->mb_type = I16MB;
    for (i=0;i<4;i++) {currMB->b8mode[i]=0; currMB->b8pdir[i]=-1; }
    currMB->cbp= ICBPTAB[(mbmode-7)>>2];
    currMB->i16mode = (mbmode-7) & 0x03;
	return;
  }
}

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

  if (mbmode==0)
  {
    currMB->mb_type = I4MB;
    for (i=0;i<4;i++) {/*currMB->b8mode[i]=IBLOCK;*/ currMB->b8pdir[i]=-1; }
	return;
  }
  else if(mbmode!=25)
  {
    currMB->mb_type = I16MB;
    for (i=0;i<4;i++) {currMB->b8mode[i]=0; currMB->b8pdir[i]=-1; }

    currMB->cbp= ICBPTAB[(mbmode-1)>>2];
    currMB->i16mode = (mbmode-1) & 0x03;
	return;
  }
  else// if(mbmode==25)
  {
    currMB->mb_type=IPCM;
    for (i=0;i<4;i++) {currMB->b8mode[i]=0; currMB->b8pdir[i]=-1; }
    currMB->cbp= -1;
    currMB->i16mode = 0;
  }
}

/*!
 ************************************************************************
 * \brief
 *    init macroblock I and P frames
 ************************************************************************
 */
void init_macroblock(struct img_par *img)
{
  int i,j;

  for (i=0;i<4;i++)
  {                           // reset vectors and pred. modes
    for(j=0;j<4;j++)
    {
      dec_picture->mv[LIST_0][img->block_x+i][img->block_y+j][0]=
      dec_picture->mv[LIST_0][img->block_x+i][img->block_y+j][1]=0;

      img->ipredmode[img->block_x+i][img->block_y+j] = DC_PRED;
    }
  }

  for (j=0; j<4; j++)
    for (i=0; i<4; i++)
    {
      dec_picture->ref_idx[LIST_0][img->block_x+i][img->block_y+j] = -1;
      dec_picture->ref_pic_id[LIST_0][img->block_x+i][img->block_y+j] = INT64_MIN;
    }
}

void reset_coeffs()
{
  int i;

  // reset luma&chroma coeffs
  memset(img->cof,0,1536);//1536 = 4*6*4*4*sizeof(int)/sizeof(byte)

  int mb_nr=img->current_mb_nr;
  // CAVLC
  for (i=0; i < 4; i++)
	  memset(img->nz_coeff[mb_nr][i],0,6*sizeof(int));
}


/*!
 ************************************************************************
 * \brief
 *    Get the syntax elements from the NAL
 ************************************************************************
 */
void read_one_macroblock(struct img_par *img)
{
  int i;

  SyntaxElement currSE;
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];

  Slice *currSlice = img->currentSlice;
  DataPartition *dP;
  int *partMap = assignSE2partition[currSlice->dp_mode];
  int  img_block_y;
//already realized in init_macroblock
//  currMB->qp = img->qp ;

  currSE.type = SE_MBTYPE;

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

  if(img->type == I_SLICE )
  {
    //  read MB type to mb_type
    dP->readSyntaxElement(&currSE,dP);

    currMB->mb_type = currSE.value1;
    if(!dP->bitstream->ei_flag)
      currMB->ei_flag = 0;

	interpret_mb_mode_I(img);

	read_ipred_modes(img);
	readCBPandCoeffsFromNAL (img);
	return;
  }

  // VLC Non-Intra
  else
  {
    if(img->cod_counter == -1)
    {
      //mb_skip_run
      dP->readSyntaxElement(&currSE,dP);
      img->cod_counter = currSE.value1;
    }
    if (img->cod_counter==0)
    {
      // read MB type to mb_type
      dP->readSyntaxElement(&currSE,dP);
      currSE.value1++; //P-Frame
      currMB->mb_type = currSE.value1;
      if(!dP->bitstream->ei_flag)
        currMB->ei_flag = 0;
      img->cod_counter--;
    } 
    else
    {
      img->cod_counter--;
      currMB->mb_type = 0;
      currMB->ei_flag = 0;
    }

	interpret_mb_mode_P(img);

	//====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ======
	if (IS_P8x8 (currMB))
	{
	 currSE.type    = SE_MBTYPE;
	 dP = &(currSlice->partArr[partMap[SE_MBTYPE]]);
	 static const int p_v2b8 [ 5] = {4, 5, 6, 7, IBLOCK};
	 static const int p_v2pd [ 5] = {0, 0, 0, 0, -1};
	 for (i=0; i<4; i++)
	 {
		 currSE.mapping = linfo_ue;
	     //sub_mb_type
	     dP->readSyntaxElement (&currSE, dP);
		 //Sets mode for 8x8 block
		 currMB->b8mode[i]   = p_v2b8[currSE.value1];
		 currMB->b8pdir[i]   = p_v2pd[currSE.value1]; 
	 }
	}

	if(img->constrained_intra_pred_flag && (img->type==P_SLICE))        // inter frame
	{
		if( !IS_INTRA(currMB) )
			img->intra_block[img->current_mb_nr] = 0;
	}
  }

  //! TO for Error Concelament
  //! If we have an INTRA Macroblock and we lost the partition
  //! which contains the intra coefficients Copy MB would be better 
  //! than just a grey block.
  //! Seems to be a bit at the wrong place to do this right here, but for this case 
  //! up to now there is no other way.
  dP = &(currSlice->partArr[partMap[SE_CBP_INTRA]]);
  if(IS_INTRA (currMB) && dP->bitstream->ei_flag && img->number)
  {
    currMB->mb_type = 0;
    currMB->ei_flag = 1;
    for (i=0;i<4;i++) {currMB->b8mode[i]=currMB->b8pdir[i]=0; }
  }
  dP = &(currSlice->partArr[partMap[currSE.type]]);
  //! End TO


  //--- init macroblock data ---
  init_macroblock       (img);

  if (IS_COPY (currMB)) //keep last macroblock
  {
    int i, j, pmv[2];
    int zeroMotionAbove;
    int zeroMotionLeft;
    PixelPos mb_a, mb_b;
    int      a_mv_y = 0;
    int      a_ref_idx = 0;
    int      b_mv_y = 0;
    int      b_ref_idx = 0;

    getLuma4x4Neighbour(img->current_mb_nr,0,0,-1, 0,&mb_a);
    getLuma4x4Neighbour(img->current_mb_nr,0,0, 0,-1,&mb_b);

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

    if (mb_b.available)
    {
      b_mv_y    = dec_picture->mv[LIST_0][mb_b.pos_x][mb_b.pos_y][1];
      b_ref_idx = dec_picture->ref_idx[LIST_0][mb_b.pos_x][mb_b.pos_y];
    }
    
    zeroMotionLeft  = !mb_a.available ? 1 : a_ref_idx==0 && dec_picture->mv[LIST_0][mb_a.pos_x][mb_a.pos_y][0]==0 && a_mv_y==0 ? 1 : 0;
    zeroMotionAbove = !mb_b.available ? 1 : b_ref_idx==0 && dec_picture->mv[LIST_0][mb_b.pos_x][mb_b.pos_y][0]==0 && b_mv_y==0 ? 1 : 0;

    currMB->cbp = 0;
    reset_coeffs();

    img_block_y   = img->block_y;
  
    if (zeroMotionAbove || zeroMotionLeft)
    {
      for(i=0;i<4;i++)
		  for(j=0;j<4;j++){
            dec_picture->mv[LIST_0][img->block_x+i][img_block_y+j][0] = 0;
            dec_picture->mv[LIST_0][img->block_x+i][img_block_y+j][1] = 0;
			dec_picture->ref_idx[LIST_0][img->block_x+i][img_block_y+j] = 0;
			dec_picture->ref_pic_id[LIST_0][img->block_x+i][img_block_y+j] 
				= dec_picture->ref_pic_num[LIST_0][dec_picture->ref_idx[LIST_0][img->block_x+i][img_block_y+j]];
		  }
    }
    else
    {
      SetMotionVectorPredictor (img, pmv, pmv+1, 0, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);
      
      for(i=0;i<4;i++)
        for(j=0;j<4;j++)
          {
            dec_picture->mv[LIST_0][img->block_x+i][img_block_y+j][0] = pmv[0];
			dec_picture->mv[LIST_0][img->block_x+i][img_block_y+j][1] = pmv[1];
			dec_picture->ref_idx[LIST_0][img->block_x+i][img_block_y+j] = 0;
			dec_picture->ref_pic_id[LIST_0][img->block_x+i][img_block_y+j] 
				= dec_picture->ref_pic_num[LIST_0][dec_picture->ref_idx[LIST_0][img->block_x+i][img_block_y+j]];

⌨️ 快捷键说明

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