📄 macroblock.c
字号:
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 + -