📄 macroblock.cpp
字号:
/*!
***********************************************************************
* \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 + -