📄 macroblock.c
字号:
// read MB mode *****************************************************************
currSE.type = SE_MBTYPE;
if(img->type == B_IMG_1 || img->type == B_IMG_MULT)
dP = &(currSlice->partArr[partMap[SE_BFRAME]]);
else
dP = &(currSlice->partArr[partMap[currSE.type]]);
if (inp->symbol_mode == UVLC || dP->bitstream->ei_flag)
currSE.mapping = linfo;
else
currSE.reading = readMB_typeInfoFromBuffer_CABAC;
if(inp->symbol_mode == CABAC || (img->type != INTER_IMG_1 && img->type != INTER_IMG_MULT && img->type != B_IMG_1 && img->type != B_IMG_MULT))
{
// read MB mode
#if TRACE
strncpy(currSE.tracestring, "MB Type", TRACESTRING_SIZE);
#endif
dP->readSyntaxElement(&currSE,img,inp,dP);
img->mb_mode = currMB->mb_type = currSE.value1;
}
else
{
if(img->cod_counter == -1)
{
#if TRACE
strncpy(currSE.tracestring, "MB runlength", TRACESTRING_SIZE);
#endif
dP->readSyntaxElement(&currSE,img,inp,dP);
img->cod_counter = currSE.value1;
}
if (img->cod_counter==0)
{
#if TRACE
strncpy(currSE.tracestring, "MB Type", TRACESTRING_SIZE);
#endif
dP->readSyntaxElement(&currSE,img,inp,dP);
if(img->type == INTER_IMG_1 || img->type == INTER_IMG_MULT)
currSE.value1++;
img->mb_mode = currMB->mb_type = currSE.value1;
img->cod_counter--;
}
else
{
img->cod_counter--;
img->mb_mode = 0;
}
}
if(img->UseConstrainedIntraPred)
{
if (img->type==INTER_IMG_1 || (img->type==INTER_IMG_MULT)) // inter frame
if (img->mb_mode < 8)
img->intra_mb[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(img->mb_mode == INTRA_MB && dP->bitstream->ei_flag && img->number)
{
img->mb_mode = COPY_MB;
img->imod = INTRA_MB_INTER;
}
if(img->type == B_IMG_1 || img->type == B_IMG_MULT)
dP = &(currSlice->partArr[partMap[SE_BFRAME]]);
else
dP = &(currSlice->partArr[partMap[currSE.type]]);
//! End TO
if ((img->type==INTER_IMG_1) || (img->type==INTER_IMG_MULT)) // inter frame
interpret_mb_mode_P(img);
else if (img->type==INTRA_IMG) // intra frame
interpret_mb_mode_I(img);
else if ((img->type==B_IMG_1) || (img->type==B_IMG_MULT)) // B frame
interpret_mb_mode_B(img);
else if ((img->type==SP_IMG_1) || (img->type==SP_IMG_MULT)) // SP frame
interpret_mb_mode_P(img);
if ((img->type==B_IMG_1) || (img->type==B_IMG_MULT))
init_macroblock_Bframe(img);
else
init_macroblock(img);
if (inp->symbol_mode != CABAC && img->imod==B_Direct && img->mb_mode==COPY_MB && img->cod_counter >= 0)
{
int i, j, iii, jjj;
currMB->cbp = 0;
for (i=0;i<BLOCK_SIZE;i++)
{ // reset luma coeffs
for (j=0;j<BLOCK_SIZE;j++)
for(iii=0;iii<BLOCK_SIZE;iii++)
for(jjj=0;jjj<BLOCK_SIZE;jjj++)
img->cof[i][j][iii][jjj]=0;
}
for (j=4;j<6;j++)
{ // reset chroma coeffs
for (i=0;i<4;i++)
for (iii=0;iii<4;iii++)
for (jjj=0;jjj<4;jjj++)
img->cof[i][j][iii][jjj]=0;
}
return DECODE_MB_BFRAME;
}
if (img->imod==INTRA_MB_INTER && img->mb_mode==COPY_MB) //keep last macroblock
{
return DECODE_COPY_MB;
}
// intra prediction modes for a macroblock 4x4 **********************************************
if (img->imod==INTRA_MB_OLD)
{
currSE.type = SE_INTRAPREDMODE;
if(img->type == B_IMG_1 || img->type == B_IMG_MULT)
dP = &(currSlice->partArr[partMap[SE_BFRAME]]);
else
dP = &(currSlice->partArr[partMap[currSE.type]]);
if (inp->symbol_mode == UVLC || dP->bitstream->ei_flag)
currSE.mapping = linfo;
else
currSE.reading = readIntraPredModeFromBuffer_CABAC;
for(i=0;i<MB_BLOCK_SIZE/2;i++)
{
#if TRACE
snprintf(currSE.tracestring, TRACESTRING_SIZE, "Intra mode ");
#endif
dP->readSyntaxElement(&currSE,img,inp,dP);
i1=img->block_x + 2*(i&0x01);
j1=img->block_y + i/2;
if (inp->symbol_mode == UVLC)
{
dbl_ipred_word = currSE.value1;
// find intra prediction mode for two blocks
img->ipredmode[i1+1][j1+1] = PRED_IPRED[img->ipredmode[i1+1][j1]+1][img->ipredmode[i1][j1+1]+1][IPRED_ORDER[dbl_ipred_word][0]];
img->ipredmode[i1+2][j1+1] = PRED_IPRED[img->ipredmode[i1+2][j1]+1][img->ipredmode[i1+1][j1+1]+1][IPRED_ORDER[dbl_ipred_word][1]];
}
else
{
img->ipredmode[i1+1][j1+1] = PRED_IPRED[img->ipredmode[i1+1][j1]+1][img->ipredmode[i1][j1+1]+1][currSE.value1];
img->ipredmode[i1+2][j1+1] = PRED_IPRED[img->ipredmode[i1+2][j1]+1][img->ipredmode[i1+1][j1+1]+1][currSE.value2];
}
}
}
// read inter frame vector data ********************************************************
if ((img->type==B_IMG_1) || (img->type==B_IMG_MULT))
readMotionInfoFromNAL_Bframe(img,inp);
else if(img->imod==INTRA_MB_INTER)
readMotionInfoFromNAL_Pframe(img,inp);
// read CBP and Coeffs ***************************************************************
readCBPandCoeffsFromNAL(img,inp);
return (((img->type==B_IMG_1) || (img->type==B_IMG_MULT)) ? DECODE_MB_BFRAME : DECODE_MB);
}
/*!
************************************************************************
* \brief
* Get for a given MB of a P picture the reference frame
* parameter and the motion vectors from the NAL
************************************************************************
*/
void readMotionInfoFromNAL_Pframe(struct img_par *img,struct inp_par *inp)
{
int i,j,k,l,m;
int step_h,step_v;
int curr_mvd;
int mb_nr = img->current_mb_nr;
Macroblock *currMB = &img->mb_data[mb_nr];
SyntaxElement currSE;
Slice *currSlice = img->currentSlice;
DataPartition *dP;
int *partMap = assignSE2partition[currSlice->dp_mode];
int ref_frame = currMB->ref_frame;
int predframe_no = currMB->predframe_no;
// keep track of neighbouring macroblocks available for prediction
int mb_width = img->width/16;
int mb_available_up = (img->mb_y == 0) ? 0 : (currMB->slice_nr == img->mb_data[mb_nr-mb_width].slice_nr);
int mb_available_left = (img->mb_x == 0) ? 0 : (currMB->slice_nr == img->mb_data[mb_nr-1].slice_nr);
int mb_available_upleft = (img->mb_x == 0 || img->mb_y == 0) ? 0 : (currMB->slice_nr == img->mb_data[mb_nr-mb_width-1].slice_nr);
int mb_available_upright = (img->mb_x >= mb_width-1 || img->mb_y == 0) ? 0 : (currMB->slice_nr == img->mb_data[mb_nr-mb_width+1].slice_nr);
// keep track of neighbouring blocks available for motion vector prediction
int block_available_up, block_available_left, block_available_upright, block_available_upleft;
int mv_a, mv_b, mv_c, mv_d;
int mvPredType, rFrameL, rFrameU, rFrameUR;
int ie, j4, i4, ii,jj;
int pred_vec=0, vec;
// If multiple ref. frames, read reference frame for the MB *********************************
if(img->type==INTER_IMG_MULT || img->type == SP_IMG_MULT)
{
#if TRACE
strncpy(currSE.tracestring, "Reference frame no ", TRACESTRING_SIZE);
#endif
currSE.type = SE_REFFRAME;
dP = &(currSlice->partArr[partMap[currSE.type]]);
if (inp->symbol_mode == UVLC || dP->bitstream->ei_flag)
currSE.mapping = linfo;
else
currSE.reading = readRefFrameFromBuffer_CABAC;
dP->readSyntaxElement(&currSE,img,inp,dP);
predframe_no = currMB->predframe_no = currSE.value1;
ref_frame = currMB->ref_frame = predframe_no;
/*!
* \note
* if frame lost occurs within img->buf_cycle frames and buffer of previous
* decoded pictures is still empty, set ref_frame to last decoded
* picture to avoid prediction from unexistent frames.
*/
// if (ref_frame > img->number) ref_frame = 0;
// Update the reference frame information for motion vector prediction
for (j = 0;j < BLOCK_SIZE;j++)
for (i = 0;i < BLOCK_SIZE;i++)
refFrArr[img->block_y+j][img->block_x+i] = predframe_no;
}
// read motion vectors **********************************************************************
currSE.type = SE_MVD;
dP = &(currSlice->partArr[partMap[currSE.type]]);
if (inp->symbol_mode == UVLC || dP->bitstream->ei_flag)
currSE.mapping = linfo_mvd;
else
currSE.reading = readMVDFromBuffer_CABAC;
step_h=BLOCK_STEP[img->mb_mode][0]; // horizontal stepsize
step_v=BLOCK_STEP[img->mb_mode][1]; // vertical stepsize
ie=4-BLOCK_STEP[img->mb_mode][0];
for (j=0; j < BLOCK_SIZE; j += step_v)
{
block_available_up = mb_available_up || (j > 0);
j4=img->block_y+j;
for (i=0;i < BLOCK_SIZE; i += step_h)
{
i4=img->block_x+i;
// first make mv-prediction
// D B C
// A X
// 1 A, B, D are set to 0 if unavailable
// 2 If C is not available it is replaced by D
block_available_left = mb_available_left || (i > 0);
if (j > 0)
block_available_upright = i != ie ? 1 : 0;
else if (i != ie)
block_available_upright = block_available_up;
else
block_available_upright = mb_available_upright;
if (i > 0)
block_available_upleft = j > 0 ? 1 : block_available_up;
else if (j > 0)
block_available_upleft = block_available_left;
else
block_available_upleft = mb_available_upleft;
mvPredType = MVPRED_MEDIAN;
rFrameL = block_available_left ? refFrArr[j4][i4-1] : -1;
rFrameU = block_available_up ? refFrArr[j4-1][i4] : -1;
rFrameUR = block_available_upright ? refFrArr[j4-1][i4+BLOCK_STEP[img->mb_mode][0]] :
block_available_upleft ? refFrArr[j4-1][i4-1] : -1;
// Prediction if only one of the neighbors uses the selected reference frame
if(rFrameL == predframe_no && rFrameU != predframe_no && rFrameUR != predframe_no)
mvPredType = MVPRED_L;
else if(rFrameL != predframe_no && rFrameU == predframe_no && rFrameUR != predframe_no)
mvPredType = MVPRED_U;
else if(rFrameL != predframe_no && rFrameU != predframe_no && rFrameUR == predframe_no)
mvPredType = MVPRED_UR;
// Directional predictions
else if(img->mb_mode == 3)
{
if(i == 0)
{
if(rFrameL == predframe_no)
mvPredType = MVPRED_L;
}
else
{
if(rFrameUR == predframe_no)
mvPredType = MVPRED_UR;
}
}
else if(img->mb_mode == 2)
{
if(j == 0)
{
if(rFrameU == predframe_no)
mvPredType = MVPRED_U;
}
else
{
if(rFrameL == predframe_no)
mvPredType = MVPRED_L;
}
}
else if(img->mb_mode == 5 && i == 2)
mvPredType = MVPRED_L;
else if(img->mb_mode == 6 && j == 2)
mvPredType = MVPRED_U;
for (k=0; k < 2; k++)
{
mv_a = block_available_left ? img->mv[i4-1+BLOCK_SIZE][j4][k] : 0;
mv_b = block_available_up ? img->mv[i4+BLOCK_SIZE][j4-1][k] : 0;
mv_d = block_available_upleft ? img->mv[i4-1+BLOCK_SIZE][j4-1][k] : 0;
mv_c = block_available_upright ? img->mv[i4+BLOCK_STEP[img->mb_mode][0]+BLOCK_SIZE][j4-1][k] : mv_d;
switch (mvPredType)
{
case MVPRED_MEDIAN:
if(!(block_available_upleft || block_available_up || block_available_upright))
pred_vec = mv_a;
else
pred_vec =mv_a+mv_b+mv_c-min(mv_a,min(mv_b,mv_c))-max(mv_a,max(mv_b,mv_c));
break;
case MVPRED_L:
pred_vec = mv_a;
break;
case MVPRED_U:
pred_vec = mv_b;
break;
case MVPRED_UR:
pred_vec = mv_c;
break;
default:
break;
}
#if TRACE
snprintf(currSE.tracestring, TRACESTRING_SIZE, " MVD");
#endif
img->subblock_x = i; // position used for context determination
img->subblock_y = j; // position used for context determination
currSE.value2 = k; // identifies the component; only used for context determination
dP->readSyntaxElement(&currSE,img,inp,dP);
curr_mvd = currSE.value1;
vec=curr_mvd+pred_vec; // find motion vector
for(ii=0;ii<BLOCK_STEP[img->mb_mode][0];ii++)
for(jj=0;jj<BLOCK_STEP[img->mb_mode][1];jj++)
img->mv[i4+ii+BLOCK_SIZE][j4+jj][k]=vec;
// store (oversampled) mvd
for (l=0; l < step_v; l++)
for (m=0; m < step_h; m++)
currMB->mvd[0][j+l][i+m][k] = curr_mvd;
}
}
}
}
/*!
************************************************************************
* \brief
* Get coded block pattern and coefficients (run/level)
* from the NAL
************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -