📄 macroblock.c
字号:
/*!
*************************************************************************************
* \file macorblock.c
*
* \brief
* decoder one macroblock
*************************************************************************************
*/
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "global.h"
#include "header.h"
#include "macroblock.h"
#include "vlc.h"
#include "defines.h"
#include "block.h"
/*!
*************************************************************************************
* \brief
* Checks the availability of neighboring macroblocks of
* the current macroblock for prediction and context determination;
* marks the unavailable MBs for intra prediction in the
* ipredmode-array by -1. Only neighboring MBs in the causal
* past of the current MB are checked.
*************************************************************************************
*/
void CheckAvailabilityOfNeighbors()
{
const int mb_width = pgImage->width/MB_BLOCK_SIZE;
const int mb_nr = pgImage->current_mb_nr;
// Check MB to the left
if(pgImage->pix_x >= MB_BLOCK_SIZE)
{
int remove_prediction = pgcurrMB->slice_nr != mb_data[mb_nr-1].slice_nr;
// upper blocks
if (remove_prediction)
{
pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y+1] = -1;
pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y+2] = -1;
pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y+3] = -1;
pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y+4] = -1;
}
}
// Check MB above
if(pgImage->pix_y >= MB_BLOCK_SIZE)
{
int remove_prediction = pgcurrMB->slice_nr != mb_data[mb_nr-mb_width].slice_nr;
// upper blocks
if (remove_prediction)
{
pgImage->ipredmode[pgImage->block4_x+1][pgImage->block4_y] = -1;
pgImage->ipredmode[pgImage->block4_x+2][pgImage->block4_y] = -1;
pgImage->ipredmode[pgImage->block4_x+3][pgImage->block4_y] = -1;
pgImage->ipredmode[pgImage->block4_x+4][pgImage->block4_y] = -1;
}
}
// Check MB left above
if(pgImage->pix_y >= MB_BLOCK_SIZE && pgImage->pix_x >= MB_BLOCK_SIZE)
{
int remove_prediction = pgcurrMB->slice_nr != mb_data[mb_nr-mb_width-1].slice_nr;
if (remove_prediction)
{
pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y] = -1;
}
}
/*
// Check MB right above
if(pgImage->pix_y >= MB_BLOCK_SIZE && pgImage->pix_x < (pgImage->width-MB_BLOCK_SIZE ))
{
//if(pgcurrMB->slice_nr == mb_data[mb_nr-mb_width+1].slice_nr)
//pgcurrMB->mb_available[0][2]=&(mb_data[mb_nr-mb_width+1]);
}
*/
}
/*!
*************************************************************************************
* \brief
* initializes the current macroblock
*************************************************************************************
*/
void start_macroblock() //qwang 2004-3-8
{
int i,j,k;
//int iii, jjj;
assert (pgImage->current_mb_nr >=0 && pgImage->current_mb_nr < pgImage->max_mb_nr);
pgcurrMB = &mb_data[pgImage->current_mb_nr];//GB
pgcurrMB->slice_nr = pgImage->current_slice_nr;//WJP FOR SLICE//
pgcurrMB->I_MODE = 1/*0 dongjie(check) */;//WJP FOR I_DIRECT
//pgcurrMB->lf_disable = pgImage->loop_filter_disable_flag;
// Update coordinates of the current macroblock
pgImage->mb_x = (pgImage->current_mb_nr)%(pgImage->width/MB_BLOCK_SIZE);
pgImage->mb_y = (pgImage->current_mb_nr)/(pgImage->width/MB_BLOCK_SIZE);
// Define vertical positions
pgImage->block4_y = pgImage->mb_y * BLOCK_SIZE; // 4x4 luma block position
pgImage->pix_y = pgImage->mb_y * MB_BLOCK_SIZE; // luma macroblock position
pgImage->pix_c_y = pgImage->mb_y * MB_BLOCK_SIZE/2; // chroma macroblock position
// Define horizontal positions
pgImage->block_x = pgImage->mb_x * BLOCK_SIZE/2; // luma block position //zhangnan //qwang 2004-3-10
pgImage->block4_x = pgImage->mb_x * BLOCK_SIZE; // 4x4 luma block position
pgImage->pix_x = pgImage->mb_x * MB_BLOCK_SIZE; // luma pixel position
pgImage->pix_c_x = pgImage->mb_x * MB_BLOCK_SIZE/2; // chroma pixel position
//need modification for intra-prediction qwang 2004-3-9 ????
// If MB is next to a slice boundary, mark neighboring blocks unavailable for prediction
CheckAvailabilityOfNeighbors();
// Reset syntax element entries in MB struct
pgcurrMB->qp = previous_qp;
pgcurrMB->mb_type = -1; /* Do not use the mb type defined in FCD 0-5*/
pgcurrMB->delta_quant = 0;
pgcurrMB->cbp = 0;
pgcurrMB->cbp_blk = 0;
pgcurrMB->c_ipred_mode= -1; //MZ
//for (l=0; l < 2; l++)
for (j=0; j < BLOCK_MULTIPLE; j++)
for (i=0; i < BLOCK_MULTIPLE; i++)
for (k=0; k < 2; k++)
pgcurrMB->mvd[j][i][k] = 0;
// initialize pgImage->m7 for ABT//Lou
for (j=0; j<MB_BLOCK_SIZE; j++)
for (i=0; i<MB_BLOCK_SIZE; i++)
pgImage->m7[i][j] = 0;
for (j=0; j<B8_SIZE; j++)
for (i=0; i<B8_SIZE; i++)
{
pgImage->m8[0][i][j] = 0;
pgImage->m8[1][i][j] = 0;
}
for (i=0;i<4;i++)
pgcurrMB->sub_mb_type[i] = 0;
for (i=0;i<4;i++) // reset vectors and pred. modes
for(j=0;j<4;j++)
{
pgImage->mv[pgImage->block4_x+i+4][pgImage->block4_y+j][0] = 0;
pgImage->mv[pgImage->block4_x+i+4][pgImage->block4_y+j][1] = 0;
pgImage->ipredmode[pgImage->block4_x+i+1][pgImage->block4_y+j+1] = (pgImage->constrained_intra_pred_flag?-1:10) ;
}
//for (j=0;j<6;j++) // reset all chroma coeffs before read
// for (i=0;i<4;i++)
// for (iii=0;iii<4;iii++)
// for (jjj=0;jjj<4;jjj++)
// pgImage->cof[i][j][iii][jjj]=0;
for (j=0; j<4; j++)
for (i=0; i<4; i++)
refFrArr[pgImage->block4_y+j][pgImage->block4_x+i] = -1;
}
/*!
*************************************************************************************
* \brief
* Get the syntax elements from the NAL
*************************************************************************************
*/
int read_one_macroblock() //qwang 2004-3-9
{
int b8;
int len, inf;//WJP FOR SUB_MB_TYPE
int i;
//read macroblock type
read_mb_type();
//read intra prediction mode currStream->frame_bitoffset
if (IS_INTRA(pgcurrMB))
{
for (b8=0;b8<4;b8++) //b8
{
read_luma_ipred_modes(b8);
}
read_chroma_ipred_modes();
}
if (IS_COPY (pgcurrMB)) //keep last macroblock
{
FindSkipMVandRef(pgcurrMB);
}
if (IS_INTERMV (pgcurrMB))
{
readReferenceIndex();
//WJP FOR SUB_MB_TYPE
//====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ======
if (IS_P8x8 (pgcurrMB))
{
for (i=0; i<4; i++)
{
len = GetVLCSymbol (&inf);
mapping_ue(len,inf,&pgcurrMB->sub_mb_type[i]);
#if TRACE
tracebits("Sub mb type", len, inf, pgcurrMB->sub_mb_type[i]);
#endif
}
}
//WJP END
//read motion information
readMotionVector ();
}
// read CBP if not new intra mode
if (!IS_COPY (pgcurrMB))
{
read_CBP_dquant(pgcurrMB);
}
// read CBP and Coeffs ***************************************************************
read_luma_chroma_coeffs();
CheckMbOverHeadValid(pgcurrMB); /* MB parameter check*/
#if TRACE
trace_mboverhead(pgcurrMB);
#endif
return DECODE_MB;
}
/*!
*************************************************************************************
* \brief
* decode intra prediction mode
*************************************************************************************
*/
const int mpm[9][9] =
{
{0, 0, 2, 0, 0, 0, 2, 0, 2},
{2, 1, 2, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 2, 2},
{2, 1, 2, 3, 4, 5, 2, 7, 2},
{4, 4, 2, 4, 4, 4, 6, 4, 4},
{5, 5, 2, 5, 5, 5, 6, 5, 5},
{6, 6, 6, 6, 6, 6, 6, 6, 6},
{7, 7, 2, 7, 7, 7, 6, 7, 7},
{0, 1, 2, 3, 4, 5, 6, 7, 8}
};
void read_luma_ipred_modes(int b8) //qwang 2004-3-9
{
int bi,bj,dec;
int b4;
SyntaxElement currSE;
int mostProbableIntraPredMode;
int upIntraPredMode;
int leftIntraPredMode;
int IntraChromaPredModeFlag;
//int MBRowSize = pgImage->width / MB_BLOCK_SIZE;
pgcurrMB=mb_data+pgImage->current_mb_nr;//current_mb_nr;
IntraChromaPredModeFlag = IS_INTRA(pgcurrMB);
currSE.type = SE_INTRAPREDMODE;
#if TRACE
strncpy(currSE.tracestring, "Intra4x4_pred_Mode", TRACESTRING_SIZE);
#endif
IntraChromaPredModeFlag = 1; //?
for(b4=0; b4<4; b4++)
{
//get from stream
if(pgcurrMB->I_MODE)//I4x4
read_Intra4x4PredictionMode(&currSE);
//get from array and decode
bi = (pgImage->block4_x + ((b8 &1)<<1) + (b4 &1));
bj = (pgImage->block4_y + ((b8>>1)<<1) + (b4>>1));
upIntraPredMode = ((pgImage->ipredmode[bi+1][bj]==10)?-1:pgImage->ipredmode[bi+1][bj]);
leftIntraPredMode = ((pgImage->ipredmode[bi][bj+1]==10)?-1:pgImage->ipredmode[bi][bj+1]);
mostProbableIntraPredMode = (upIntraPredMode < 0 || leftIntraPredMode < 0) ? DC_PRED : mpm[leftIntraPredMode][upIntraPredMode];
dec = (currSE.value1 == -1) ? mostProbableIntraPredMode : currSE.value1 + (currSE.value1 >= mostProbableIntraPredMode);
pgImage->ipredmode[1+bi][1+bj]=dec;
/* bistream conformance check -- zhan ma*/
stat_parameter->intra_luma_pred_mode[dec] = 1;
#if TRACE
MB_ipredmode_Y[((b8>>1)<<1) + (b4>>1)][((b8 &1)<<1) + (b4 &1)]=dec;
#endif
if(!pgcurrMB->I_MODE) // added by dongjie(check)
pgImage->ipredmode[1+bi][1+bj]=mostProbableIntraPredMode;
#if TRACE
MB_ipredmode_Y[((b8>>1)<<1) + (b4>>1)][((b8 &1)<<1) + (b4 &1)]=dec;
#endif
}
}
/*!
*************************************************************************************
* \brief
* decode intra chroma prediction mode
*************************************************************************************
*/
void read_chroma_ipred_modes() //qwang 2004-3-9
{
SyntaxElement currSE;
int IntraChromaPredModeFlag;
pgcurrMB=mb_data+pgImage->current_mb_nr;//current_mb_nr;
IntraChromaPredModeFlag = IS_INTRA(pgcurrMB);
currSE.type = SE_INTRAPREDMODE;
#if TRACE
strncpy(currSE.tracestring, "intra_Chroma_pred_mode", TRACESTRING_SIZE);
#endif
currSE.mapping = mapping_ue;
read_UVLC(&currSE);
pgcurrMB->c_ipred_mode = currSE.value1;
/* bistream conformance check -- zhan ma */
stat_parameter->intra_chroma_pred_mode[pgcurrMB->c_ipred_mode] = 1;
if (currSE.value1 < DC_PRED_8 || currSE.value1 > VERT_PRED_8)
{
printf("%d\n", pgImage->current_mb_nr);
error("illegal chroma intra pred mode!\n", 600);
}
}
/*!
*************************************************************************************
* \brief
* readReferenceIndex
*************************************************************************************
*/
void readReferenceIndex()
{
int i,j,k;
SyntaxElement currSE;
int partmode = (IS_P8x8(pgcurrMB)?4:pgcurrMB->mb_type);
int step_h0 = BLOCK_STEP [partmode][0];
int step_v0 = BLOCK_STEP [partmode][1];
int i0, j0, refframe;
int flag_mode;
// If multiple ref. frames, read reference frame for the MB *********************************
flag_mode = 0;
currSE.type = SE_REFFRAME;
currSE.mapping = mapping_ue;
// !! shenyanfei
for (j0=0; j0<4; j0+=step_v0)
for (i0=0; i0<4; i0+=step_h0)
{
k=2*(j0/2)+(i0/2);
if (pgcurrMB->mb_type!=SKIP_MB)//WJP FOR ZERO_REF
{
if ((pgImage->num_ref_frames == 2)&&(!pgImage->picture_reference_flag)&&(!pgImage->is_ref0_an_IDR)) /* added by zhan ma*/
{
#if TRACE
strncpy(currSE.tracestring, "Fwd ref frame no ", TRACESTRING_SIZE);
#endif
currSE.len = 1;
read_FLC(&currSE);
refframe = currSE.value1;
}
else
{
refframe = 0;
}
for (j=j0; j<j0+step_v0;j++)
for (i=i0; i<i0+step_h0;i++)
refFrArr[pgImage->block4_y+j][pgImage->block4_x+i] = refframe;
}
else
{
for (j=j0; j<j0+step_v0;j++)
for (i=i0; i<i0+step_h0;i++)
refFrArr[pgImage->block4_y+j][pgImage->block4_x+i] = 0;
}
}
}
/*!
*************************************************************************************
* \brief
* readMotionVector
*************************************************************************************
*/
void readMotionVector()
{
int i,j,k,l,m;
int step_h,step_v;
int curr_mvd;
SyntaxElement currSE;
int partmode = (IS_P8x8(pgcurrMB)?4:pgcurrMB->mb_type);
int step_h0 = BLOCK_STEP [partmode][0];
int step_v0 = BLOCK_STEP [partmode][1];
int i0, j0, refframe;
int pmv[2];
int j4, i4, ii,jj;
int vec;
//===== READ FORWARD MOTION VECTORS =====
currSE.type = SE_MVD;
currSE.mapping = mapping_se;
for (j0=0; j0<4; j0+=step_v0)
for (i0=0; i0<4; i0+=step_h0)
{
k=2*(j0/2)+(i0/2);
step_h = BLOCK_STEP [pgcurrMB->mb_type +pgcurrMB->sub_mb_type[k]][0];
step_v = BLOCK_STEP [pgcurrMB->mb_type +pgcurrMB->sub_mb_type[k]][1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -