您的位置:首页 > 其它

如何利用JM8.6解码器提取码流中P帧宏块的运动矢量(假设编码不用B帧,仅为IDR P P)

2012-12-28 16:42 399 查看
       在H.264的P帧中,可能有I宏块,skip形式的P宏块和非skip形式的P宏块, I宏块自然不存在运动矢量这一说法. 而skip形式的P宏块和非skip形式的P宏块都是由运动矢量的.(前面已经说过,对于skip形式的宏块而言,像素残差和运动矢量残差都为0)

       本人编码3帧,I(IDR) P1 P2. 视频格式是qcif,所以每帧的宏块个数为:99.

       用H.264visa分析发现:

       I帧中共有99个I宏块;

       P1中有67个非skip形式的P宏块, 32个skip形式的P宏块;

       P2中有25个非skip形式的P宏块,72个skip形式的P宏块,2个I宏块.

 

      下面先来看看JM8.6解码器中一个非常重要的函数read_one_macroblock

// 下面注释均假设:
// 1.编码形式为:I(IDR) P P
// 2.I帧中共有99个I宏块;
// 3.P1中有67个非skip形式的P宏块,32个skip形式的P宏块;
// 4.P2中有25个非skip形式的P宏块,72个skip形式的P宏块,2个I宏块.

int read_one_macroblock(struct img_par *img,struct inp_par *inp)
{
// 3帧,共99 * 3个宏块,该函数也刚好被调用297次

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];
Macroblock *topMB = NULL;
int  prevMbSkipped = 0;
int  img_block_y;
int  check_bottom, read_bottom, read_top;

if (img->MbaffFrameFlag)
{
if (img->current_mb_nr%2)
{
topMB= &img->mb_data[img->current_mb_nr-1];
if(!(img->type == B_SLICE))
prevMbSkipped = (topMB->mb_type == 0);
else
prevMbSkipped = (topMB->mb_type == 0 && topMB->cbp == 0);
}
else
prevMbSkipped = 0;
}

if (img->current_mb_nr%2 == 0)
currMB->mb_field = 0;
else
currMB->mb_field = img->mb_data[img->current_mb_nr-1].mb_field;

currMB->qp = img->qp ;

currSE.type = SE_MBTYPE;

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

if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
currSE.mapping = linfo_ue;

if(img->type == I_SLICE || img->type == SI_SLICE)
{
// I帧(片)中的宏块,刚好99个, 刚好被调用99次

// read MB aff
if (img->MbaffFrameFlag && img->current_mb_nr%2==0)
{
TRACE_STRING("mb_field_decoding_flag");
if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
{
currSE.len = 1;
readSyntaxElement_FLC(&currSE, dP->bitstream);
}
else
{
currSE.reading = readFieldModeInfo_CABAC;
dP->readSyntaxElement(&currSE,img,inp,dP);
}
currMB->mb_field = currSE.value1;
}
if(active_pps->entropy_coding_mode_flag  == CABAC)
CheckAvailabilityOfNeighborsCABAC();

//  read MB type
TRACE_STRING("mb_type");
currSE.reading = readMB_typeInfo_CABAC;
dP->readSyntaxElement(&currSE,img,inp,dP);

currMB->mb_type = currSE.value1;
if(!dP->bitstream->ei_flag)
currMB->ei_flag = 0;
}
// non I/SI-slice CABAC
else if (active_pps->entropy_coding_mode_flag == CABAC)
{
// read MB skipflag
if (img->MbaffFrameFlag && (img->current_mb_nr%2 == 0||prevMbSkipped))
field_flag_inference();

CheckAvailabilityOfNeighborsCABAC();
TRACE_STRING("mb_skip_flag");
currSE.reading = readMB_skip_flagInfo_CABAC;
dP->readSyntaxElement(&currSE,img,inp,dP);
currMB->mb_type = currSE.value1;

if (img->type==B_SLICE)
currMB->cbp = currSE.value2;
if(!dP->bitstream->ei_flag)
currMB->ei_flag = 0;

if ((img->type==B_SLICE) && currSE.value1==0 && currSE.value2==0)
img->cod_counter=0;

// read MB aff
if (img->MbaffFrameFlag)
{
check_bottom=read_bottom=read_top=0;
if (img->current_mb_nr%2==0)
{
check_bottom =  (img->type!=B_SLICE)?
(currMB->mb_type == 0):
(currMB->mb_type == 0 && currMB->cbp == 0);
read_top = !check_bottom;
}
else
read_bottom = (img->type!=B_SLICE)?
(topMB->mb_type == 0 && currMB->mb_type != 0) :
((topMB->mb_type == 0 && topMB->cbp == 0) && (currMB->mb_type != 0 || currMB->cbp != 0));

if (read_bottom || read_top)
{
TRACE_STRING("mb_field_decoding_flag");
currSE.reading = readFieldModeInfo_CABAC;
dP->readSyntaxElement(&currSE,img,inp,dP);
currMB->mb_field = currSE.value1;
}
if (check_bottom)
check_next_mb_and_get_field_mode_CABAC(&currSE,img,inp,dP);

}
if(active_pps->entropy_coding_mode_flag  == CABAC)
CheckAvailabilityOfNeighborsCABAC();

// read MB type
if (currMB->mb_type != 0 )
{
currSE.reading = readMB_typeInfo_CABAC;
TRACE_STRING("mb_type");
dP->readSyntaxElement(&currSE,img,inp,dP);
currMB->mb_type = currSE.value1;
if(!dP->bitstream->ei_flag)
currMB->ei_flag = 0;
}
}
// VLC Non-Intra
else
{
// 第1个P帧对应99个宏块,此处被调用99次
// 第2个P帧对应99个宏块,此处被调用99次

if(img->cod_counter == -1)
{
TRACE_STRING("mb_skip_run");
dP->readSyntaxElement(&currSE,img,inp,dP);
img->cod_counter = currSE.value1;
}
if (img->cod_counter==0)
{
// read MB aff
if ((img->MbaffFrameFlag) && ((img->current_mb_nr%2==0) || ((img->current_mb_nr%2) && prevMbSkipped)))
{
TRACE_STRING("mb_field_decoding_flag");
currSE.len = 1;
readSyntaxElement_FLC(&currSE, dP->bitstream);
currMB->mb_field = currSE.value1;
}

// read MB type
TRACE_STRING("mb_type");
dP->readSyntaxElement(&currSE,img,inp,dP);
if(img->type == P_SLICE || img->type == SP_SLICE)
currSE.value1++;
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;

// read field flag of bottom block
if(img->MbaffFrameFlag)
{
if(img->cod_counter == 0 && (img->current_mb_nr%2 == 0))
{
TRACE_STRING("mb_field_decoding_flag (of coded bottom mb)");
currSE.len = 1;
readSyntaxElement_FLC(&currSE, dP->bitstream);
dP->bitstream->frame_bitoffset--;
currMB->mb_field = currSE.value1;
}
else if(img->cod_counter > 0 && (img->current_mb_nr%2 == 0))
{
// check left macroblock pair first
if (mb_is_available(img->current_mb_nr-2, img->current_mb_nr)&&((img->current_mb_nr%(img->PicWidthInMbs*2))!=0))
{
currMB->mb_field = img->mb_data[img->current_mb_nr-2].mb_field;
}
else
{
// check top macroblock pair
if (mb_is_available(img->current_mb_nr-2*img->PicWidthInMbs, img->current_mb_nr))
{
currMB->mb_field = img->mb_data[img->current_mb_nr-2*img->PicWidthInMbs].mb_field;
}
else
currMB->mb_field = 0;
}
}
}
}
}

// 此处被调用297次

dec_picture->mb_field[img->current_mb_nr] = currMB->mb_field;

img->siblock[img->mb_x][img->mb_y]=0;

if ((img->type==P_SLICE ))    // inter frame
interpret_mb_mode_P(img);
else if (img->type==I_SLICE)                                  // intra frame
interpret_mb_mode_I(img);
else if ((img->type==B_SLICE))       // B frame
interpret_mb_mode_B(img);
else if ((img->type==SP_SLICE))     // SP frame
interpret_mb_mode_P(img);
else if (img->type==SI_SLICE)     // SI frame
interpret_mb_mode_SI(img);

if(img->MbaffFrameFlag)
{
if(currMB->mb_field)
{
img->num_ref_idx_l0_active <<=1;
img->num_ref_idx_l1_active <<=1;
}
}

// 下面这些代码非常重要

//====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ======
if (IS_P8x8 (currMB))
{
// I帧,此处被调用0次
// 第一个P帧时候,此处被调用15次,该P帧中刚好有15个8*8的P宏块
// 第一个P帧时候,此处被调用15次,该P帧中刚好有15个8*8的P宏块

currSE.type    = SE_MBTYPE;
dP = &(currSlice->partArr[partMap[SE_MBTYPE]]);

for (i=0; i<4; i++)
{
if (active_pps->entropy_coding_mode_flag ==UVLC || dP->bitstream->ei_flag)
currSE.mapping = linfo_ue;
else
currSE.reading = readB8_typeInfo_CABAC;

TRACE_STRING("sub_mb_type");
dP->readSyntaxElement (&currSE, img, inp, dP);
SetB8Mode (img, currMB, currSE.value1, i);
}
}

if(active_pps->constrained_intra_pred_flag && (img->type==P_SLICE|| img->type==B_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_DIRECT (currMB) && img->cod_counter >= 0)
{
currMB->cbp = 0;
reset_coeffs();

if (active_pps->entropy_coding_mode_flag ==CABAC)
img->cod_counter=-1;

return DECODE_MB;
}

// 程序到此处 297次

if (IS_COPY (currMB)) //keep last macroblock
{
int i, j, k, 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;
int      list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? img->current_mb_nr%2 ? 4 : 2 : 0;

// 对于I帧,此处被调用0次
// 对于第1个P帧,此处被调用了32次
// 对于第2个P帧,此处被调用了25次
// 发现:调用次数为skip形式的P宏块的个数

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 (currMB->mb_field && !img->mb_data[mb_a.mb_addr].mb_field)
{
a_mv_y    /=2;
a_ref_idx *=2;
}
if (!currMB->mb_field && img->mb_data[mb_a.mb_addr].mb_field)
{
a_mv_y    *=2;
a_ref_idx >>=1;
}
}

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];

if (currMB->mb_field && !img->mb_data[mb_b.mb_addr].mb_field)
{
b_mv_y    /=2;
b_ref_idx *=2;
}
if (!currMB->mb_field && img->mb_data[mb_b.mb_addr].mb_field)
{
b_mv_y    *=2;
b_ref_idx >>=1;
}
}

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)
{
// skip形式的P宏块,设置运动矢量为(0,0)
fprintf(myMV, "%-4d %-4d", 0, 0);
controlFlag++;
if(0 == controlFlag % 4)
{
fprintf(mySkipMV, "\n\n");
controlFlag = 0;
}

// 每个 4 * 4块都存
for(i=0;i<BLOCK_SIZE;i++)
for(j=0;j<BLOCK_SIZE;j++)
for (k=0;k<2;k++)
dec_picture->mv[LIST_0][img->block_x+i][img->block_y+j][k] = 0;
}
else
{
SetMotionVectorPredictor (img, pmv, pmv+1, 0, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);

// skip形式的P宏块,运动矢量为(pmv[0], pmv[1])
fprintf(mySkipMV, "%-4d %-4d", pmv[0], pmv[1]);
controlFlag++;
if(0 == controlFlag % 4)
{
fprintf(mySkipMV, "\n\n");
controlFlag = 0;
}
// 每一个4 * 4块都存
for(i=0;i<BLOCK_SIZE;i++)
for(j=0;j<BLOCK_SIZE;j++)
for (k=0;k<2;k++)
{
dec_picture->mv[LIST_0][img->block_x+i][img_block_y+j][k] = pmv[k];
}
}

for(i=0;i<BLOCK_SIZE;i++)
for(j=0;j<BLOCK_SIZE;j++)
{
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[img->current_slice_nr][LIST_0 + list_offset][dec_picture->ref_idx[LIST_0][img->block_x+i][img_block_y+j]];
}

return DECODE_MB;
}

if(currMB->mb_type!=IPCM)
{
// 对于I帧,此处被调用99次                     注:99个I宏块
// 对于第1个P帧,下面函数被调用了67次          注:67个非skip的P宏块
// 对于第2个P帧,下面的函数被调用了(72+2)次  注:72个非skip的P宏块,2个I宏块

// intra prediction modes for a macroblock 4x4 **********************************************
read_ipred_modes(img,inp);

// read inter frame vector data *********************************************************
if (IS_INTERMV (currMB))
{
// 对于第1个P帧,下面函数被调用了67次
// 对于第2个P帧,下面的函数被调用了72次

// 这个函数很重要,非skip形式的P宏块的运动矢量的提取就靠它
readMotionInfoFromNAL (img, inp);
}

// read CBP and Coeffs  ***************************************************************
readCBPandCoeffsFromNAL (img,inp);
}
else
{
//read pcm_alignment_zero_bit and pcm_byte[i]

// here dP is assigned with the same dP as SE_MBTYPE, because IPCM syntax is in the
// same category as MBTYPE
dP = &(currSlice->partArr[partMap[SE_MBTYPE]]);
readIPCMcoeffsFromNAL(img,inp,dP);
}

return DECODE_MB;
}

      上面这段代码能正确提取skip形式的P宏块的运动矢量,而非skip形式的P形式的P宏块的提取则在readMotionInfoFromNAL函数中,我们来看看这个函数:

     

// 对于非skip形式的P宏块,下面这个函数才会得到调用

void readMotionInfoFromNAL (struct img_par *img, struct inp_par *inp)
{
static int controlFlag = 0;
int i,j,k;
int step_h,step_v;
int curr_mvd;
Macroblock *currMB  = &img->mb_data[img->current_mb_nr];
SyntaxElement currSE;
Slice *currSlice    = img->currentSlice;
DataPartition *dP;
int *partMap        = assignSE2partition[currSlice->dp_mode];
int bframe          = (img->type==B_SLICE);
int partmode        = (IS_P8x8(currMB)?4:currMB->mb_type);
int step_h0         = BLOCK_STEP [partmode][0];
int step_v0         = BLOCK_STEP [partmode][1];

int mv_mode, i0, j0, refframe;
int pmv[2];
int j4, i4, ii,jj;
int vec;

int mv_scale = 0;

int flag_mode;

int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? img->current_mb_nr%2 ? 4 : 2 : 0;

byte **    moving_block;
int ****   co_located_mv;
int ***    co_located_ref_idx;
int64 ***    co_located_ref_id;

if ((img->MbaffFrameFlag)&&(currMB->mb_field))
{
if(img->current_mb_nr%2)
{
moving_block = Co_located->bottom_moving_block;
co_located_mv = Co_located->bottom_mv;
co_located_ref_idx = Co_located->bottom_ref_idx;
co_located_ref_id = Co_located->bottom_ref_pic_id;
}
else
{
moving_block = Co_located->top_moving_block;
co_located_mv = Co_located->top_mv;
co_located_ref_idx = Co_located->top_ref_idx;
co_located_ref_id = Co_located->top_ref_pic_id;
}
}
else
{
moving_block = Co_located->moving_block;
co_located_mv = Co_located->mv;
co_located_ref_idx = Co_located->ref_idx;
co_located_ref_id = Co_located->ref_pic_id;
}

if (bframe && IS_P8x8 (currMB))
{
if (img->direct_type)
{
int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr%2) ? (img->block_y-4)/2:img->block_y/2: img->block_y;
int fw_rFrameL, fw_rFrameU, fw_rFrameUL, fw_rFrameUR;
int bw_rFrameL, bw_rFrameU, bw_rFrameUL, bw_rFrameUR;

PixelPos mb_left, mb_up, mb_upleft, mb_upright;

int fw_rFrame,bw_rFrame;
int pmvfw[2]={0,0},pmvbw[2]={0,0};

getLuma4x4Neighbour(img->current_mb_nr, 0, 0, -1,  0, &mb_left);
getLuma4x4Neighbour(img->current_mb_nr, 0, 0,  0, -1, &mb_up);
getLuma4x4Neighbour(img->current_mb_nr, 0, 0, 16, -1, &mb_upright);
getLuma4x4Neighbour(img->current_mb_nr, 0, 0, -1, -1, &mb_upleft);

if (!img->MbaffFrameFlag)
{
fw_rFrameL = mb_left.available ? dec_picture->ref_idx[LIST_0][mb_left.pos_x][mb_left.pos_y] : -1;
fw_rFrameU = mb_up.available ? dec_picture->ref_idx[LIST_0][mb_up.pos_x][mb_up.pos_y] : -1;
fw_rFrameUL = mb_upleft.available ? dec_picture->ref_idx[LIST_0][mb_upleft.pos_x][mb_upleft.pos_y] : -1;
fw_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_0][mb_upright.pos_x][mb_upright.pos_y] : fw_rFrameUL;

bw_rFrameL = mb_left.available ? dec_picture->ref_idx[LIST_1][mb_left.pos_x][mb_left.pos_y] : -1;
bw_rFrameU = mb_up.available ? dec_picture->ref_idx[LIST_1][mb_up.pos_x][mb_up.pos_y] : -1;
bw_rFrameUL = mb_upleft.available ? dec_picture->ref_idx[LIST_1][mb_upleft.pos_x][mb_upleft.pos_y] : -1;
bw_rFrameUR = mb_upright.available ? dec_picture->ref_idx[LIST_1][mb_upright.pos_x][mb_upright.pos_y] : bw_rFrameUL;
}
else
{
if (img->mb_data[img->current_mb_nr].mb_field)
{
fw_rFrameL = mb_left.available ?
img->mb_data[mb_left.mb_addr].mb_field  || dec_picture->ref_idx[LIST_0][mb_left.pos_x][mb_left.pos_y] < 0?
dec_picture->ref_idx[LIST_0][mb_left.pos_x][mb_left.pos_y] :
dec_picture->ref_idx[LIST_0][mb_left.pos_x][mb_left.pos_y] * 2: -1;
fw_rFrameU = mb_up.available ?
img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_x][mb_up.pos_y] < 0?
dec_picture->ref_idx[LIST_0][mb_up.pos_x][mb_up.pos_y] :
dec_picture->ref_idx[LIST_0][mb_up.pos_x][mb_up.pos_y] * 2: -1;

fw_rFrameUL = mb_upleft.available ?
img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_x][mb_upleft.pos_y] < 0?
dec_picture->ref_idx[LIST_0][mb_upleft.pos_x][mb_upleft.pos_y] :
dec_picture->ref_idx[LIST_0][mb_upleft.pos_x][mb_upleft.pos_y] *2: -1;

fw_rFrameUR = mb_upright.available ?
img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_x][mb_upright.pos_y] < 0 ?
dec_picture->ref_idx[LIST_0][mb_upright.pos_x][mb_upright.pos_y] :
dec_picture->ref_idx[LIST_0][mb_upright.pos_x][mb_upright.pos_y] * 2: fw_rFrameUL;

bw_rFrameL = mb_left.available ?
img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_x][mb_left.pos_y]  < 0 ?
dec_picture->ref_idx[LIST_1][mb_left.pos_x][mb_left.pos_y] :
dec_picture->ref_idx[LIST_1][mb_left.pos_x][mb_left.pos_y] * 2: -1;

bw_rFrameU = mb_up.available ?
img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_x][mb_up.pos_y]  < 0 ?
dec_picture->ref_idx[LIST_1][mb_up.pos_x][mb_up.pos_y] :
dec_picture->ref_idx[LIST_1][mb_up.pos_x][mb_up.pos_y] * 2: -1;

bw_rFrameUL = mb_upleft.available ?
img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_x][mb_upleft.pos_y]  < 0 ?
dec_picture->ref_idx[LIST_1][mb_upleft.pos_x][mb_upleft.pos_y] :
dec_picture->ref_idx[LIST_1][mb_upleft.pos_x][mb_upleft.pos_y] *2: -1;

bw_rFrameUR = mb_upright.available ?
img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_x][mb_upright.pos_y]  < 0 ?
dec_picture->ref_idx[LIST_1][mb_upright.pos_x][mb_upright.pos_y] :
dec_picture->ref_idx[LIST_1][mb_upright.pos_x][mb_upright.pos_y] * 2: bw_rFrameUL;

}
else
{
fw_rFrameL = mb_left.available ?
img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_left.pos_x][mb_left.pos_y]  < 0 ?
dec_picture->ref_idx[LIST_0][mb_left.pos_x][mb_left.pos_y] >> 1 :
dec_picture->ref_idx[LIST_0][mb_left.pos_x][mb_left.pos_y]: -1;

fw_rFrameU = mb_up.available ?
img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_up.pos_x][mb_up.pos_y]  < 0 ?
dec_picture->ref_idx[LIST_0][mb_up.pos_x][mb_up.pos_y] >> 1 :
dec_picture->ref_idx[LIST_0][mb_up.pos_x][mb_up.pos_y] : -1;

fw_rFrameUL = mb_upleft.available ?
img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upleft.pos_x][mb_upleft.pos_y] < 0 ?
dec_picture->ref_idx[LIST_0][mb_upleft.pos_x][mb_upleft.pos_y]>> 1 :
dec_picture->ref_idx[LIST_0][mb_upleft.pos_x][mb_upleft.pos_y] : -1;

fw_rFrameUR = mb_upright.available ?
img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_0][mb_upright.pos_x][mb_upright.pos_y]  < 0 ?
dec_picture->ref_idx[LIST_0][mb_upright.pos_x][mb_upright.pos_y] >> 1 :
dec_picture->ref_idx[LIST_0][mb_upright.pos_x][mb_upright.pos_y] : fw_rFrameUL;

bw_rFrameL = mb_left.available ?
img->mb_data[mb_left.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_left.pos_x][mb_left.pos_y] < 0 ?
dec_picture->ref_idx[LIST_1][mb_left.pos_x][mb_left.pos_y] >> 1 :
dec_picture->ref_idx[LIST_1][mb_left.pos_x][mb_left.pos_y] : -1;
bw_rFrameU = mb_up.available ?
img->mb_data[mb_up.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_up.pos_x][mb_up.pos_y] < 0 ?
dec_picture->ref_idx[LIST_1][mb_up.pos_x][mb_up.pos_y] >> 1 :
dec_picture->ref_idx[LIST_1][mb_up.pos_x][mb_up.pos_y] : -1;

bw_rFrameUL = mb_upleft.available ?
img->mb_data[mb_upleft.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upleft.pos_x][mb_upleft.pos_y]  < 0 ?
dec_picture->ref_idx[LIST_1][mb_upleft.pos_x][mb_upleft.pos_y] >> 1 :
dec_picture->ref_idx[LIST_1][mb_upleft.pos_x][mb_upleft.pos_y] : -1;

bw_rFrameUR = mb_upright.available ?
img->mb_data[mb_upright.mb_addr].mb_field || dec_picture->ref_idx[LIST_1][mb_upright.pos_x][mb_upright.pos_y] < 0 ?
dec_picture->ref_idx[LIST_1][mb_upright.pos_x][mb_upright.pos_y] >> 1:
dec_picture->ref_idx[LIST_1][mb_upright.pos_x][mb_upright.pos_y] : bw_rFrameUL;
}
}

fw_rFrame = (fw_rFrameL >= 0 && fw_rFrameU >= 0) ? min(fw_rFrameL,fw_rFrameU): max(fw_rFrameL,fw_rFrameU);
fw_rFrame = (fw_rFrame >= 0 && fw_rFrameUR >= 0) ? min(fw_rFrame,fw_rFrameUR): max(fw_rFrame,fw_rFrameUR);

bw_rFrame = (bw_rFrameL >= 0 && bw_rFrameU >= 0) ? min(bw_rFrameL,bw_rFrameU): max(bw_rFrameL,bw_rFrameU);
bw_rFrame = (bw_rFrame >= 0 && bw_rFrameUR >= 0) ? min(bw_rFrame,bw_rFrameUR): max(bw_rFrame,bw_rFrameUR);

if (fw_rFrame >=0)
SetMotionVectorPredictor (img, pmvfw, pmvfw+1, fw_rFrame, LIST_0, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);

if (bw_rFrame >=0)
SetMotionVectorPredictor (img, pmvbw, pmvbw+1, bw_rFrame, LIST_1, dec_picture->ref_idx, dec_picture->mv, 0, 0, 16, 16);

for (i=0;i<4;i++)
{
if (currMB->b8mode[i] == 0)
for(j=2*(i/2);j<2*(i/2)+2;j++)
for(k=2*(i%2);k<2*(i%2)+2;k++)
{
int j6 = imgblock_y+j;
j4 = img->block_y+j;
i4 = img->block_x+k;

if (fw_rFrame >= 0)
{

if  (!fw_rFrame  && ((!moving_block[i4][j6]) && (!listX[1+list_offset][0]->is_long_term)))
{
dec_picture->mv  [LIST_0][i4][j4][0] = 0;
dec_picture->mv  [LIST_0][i4][j4][1] = 0;
dec_picture->ref_idx[LIST_0][i4][j4] = 0;
}
else
{

dec_picture->mv  [LIST_0][i4][j4][0] = pmvfw[0];
dec_picture->mv  [LIST_0][i4][j4][1] = pmvfw[1];
dec_picture->ref_idx[LIST_0][i4][j4] = fw_rFrame;
}
}
else
{
dec_picture->mv  [LIST_0][i4][j4][0] = 0;
dec_picture->mv  [LIST_0][i4][j4][1] = 0;
dec_picture->ref_idx[LIST_0][i4][j4] = -1;
}
if (bw_rFrame >= 0)
{
if  (bw_rFrame==0 && ((!moving_block[i4][j6])&& (!listX[1+list_offset][0]->is_long_term)))
{
dec_picture->mv  [LIST_1][i4][j4][0] = 0;
dec_picture->mv  [LIST_1][i4][j4][1] = 0;
dec_picture->ref_idx[LIST_1][i4][j4] = 0;
}
else
{
dec_picture->mv  [LIST_1][i4][j4][0] = pmvbw[0];
dec_picture->mv  [LIST_1][i4][j4][1] = pmvbw[1];
dec_picture->ref_idx[LIST_1][i4][j4] = bw_rFrame;
}
}
else
{
dec_picture->mv  [LIST_1][i4][j4][0] = 0;
dec_picture->mv  [LIST_1][i4][j4][1] = 0;
dec_picture->ref_idx[LIST_1][i4][j4] = -1;
}

if (fw_rFrame <0 && bw_rFrame <0)
{
dec_picture->ref_idx[LIST_0][i4][j4] = 0;
dec_picture->ref_idx[LIST_1][i4][j4] = 0;
}
}
}
}
else
{
for (i=0;i<4;i++)
{
if (currMB->b8mode[i] == 0)
{

for(j=2*(i/2);j<2*(i/2)+2;j++)
{
for(k=2*(i%2);k<2*(i%2)+2;k++)
{

int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? img->current_mb_nr%2 ? 4 : 2 : 0;
int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr%2) ? (img->block_y-4)/2 : img->block_y/2 : img->block_y;
int refList = co_located_ref_idx[LIST_0 ][img->block_x+k][imgblock_y+j]== -1 ? LIST_1 : LIST_0;
int ref_idx = co_located_ref_idx[refList][img->block_x + k][imgblock_y + j];
int mapped_idx=-1, iref;

if (ref_idx == -1)
{
dec_picture->ref_idx [LIST_0][img->block_x + k][img->block_y + j] = 0;
dec_picture->ref_idx [LIST_1][img->block_x + k][img->block_y + j] = 0;
}
else
{
for (iref=0;iref<min(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]);iref++)
{
if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][img->block_x + k][imgblock_y + j])
{
mapped_idx=iref;
break;
}
else //! invalid index. Default to zero even though this case should not happen
mapped_idx=INVALIDINDEX;
}
if (INVALIDINDEX == mapped_idx)
{
error("temporal direct error\ncolocated block has ref that is unavailable",-1111);
}
dec_picture->ref_idx [LIST_0][img->block_x + k][img->block_y + j] = mapped_idx;
dec_picture->ref_idx [LIST_1][img->block_x + k][img->block_y + j] = 0;
}
}
}
}
}
}
}

//  If multiple ref. frames, read reference frame for the MB *********************************
if(img->num_ref_idx_l0_active>1)
{
flag_mode = ( img->num_ref_idx_l0_active == 2 ? 1 : 0);

currSE.type = SE_REFFRAME;
dP = &(currSlice->partArr[partMap[SE_REFFRAME]]);

if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)   currSE.mapping = linfo_ue;
else                                                      currSE.reading = readRefFrame_CABAC;

for (j0=0; j0<4; j0+=step_v0)
{
for (i0=0; i0<4; i0+=step_h0)
{
k=2*(j0/2)+(i0/2);
if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)
{
TRACE_STRING("ref_idx_l0");

img->subblock_x = i0;
img->subblock_y = j0;

if (!IS_P8x8 (currMB) || bframe || (!bframe && !img->allrefzero))
{
currSE.context = BType2CtxRef (currMB->b8mode[k]);
if( (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) && flag_mode )
{
currSE.len = 1;
readSyntaxElement_FLC(&currSE, dP->bitstream);
currSE.value1 = 1 - currSE.value1;
}
else
{
currSE.value2 = LIST_0;
dP->readSyntaxElement (&currSE,img,inp,dP);
}
refframe = currSE.value1;

}
else
{
refframe = 0;
}

/*
if (bframe && refframe>img->buf_cycle)    // img->buf_cycle should be correct for field MBs now
{
set_ec_flag(SE_REFFRAME);
refframe = 1;
}
*/

for (j=j0; j<j0+step_v0;j++)
for (i=i0; i<i0+step_h0;i++)
{
dec_picture->ref_idx[LIST_0][img->block_x + i][img->block_y + j] = refframe;
}

}
}
}
}
else
{
for (j0=0; j0<4; j0+=step_v0)
{
for (i0=0; i0<4; i0+=step_h0)
{
k=2*(j0/2)+(i0/2);
if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)
{
for (j=j0; j<j0+step_v0;j++)
for (i=i0; i<i0+step_h0;i++)
{
dec_picture->ref_idx[LIST_0][img->block_x + i][img->block_y + j] = 0;
}
}
}
}
}

//  If backward multiple ref. frames, read backward reference frame for the MB *********************************
if(img->num_ref_idx_l1_active>1)
{
flag_mode = ( img->num_ref_idx_l1_active == 2 ? 1 : 0);

currSE.type = SE_REFFRAME;
dP = &(currSlice->partArr[partMap[SE_REFFRAME]]);
if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag)
currSE.mapping = linfo_ue;
else                                                      currSE.reading = readRefFrame_CABAC;
for (j0=0; j0<4; j0+=step_v0)
{
for (i0=0; i0<4; i0+=step_h0)
{
k=2*(j0/2)+(i0/2);
if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)
{
TRACE_STRING("ref_idx_l1");

img->subblock_x = i0;
img->subblock_y = j0;

currSE.context = BType2CtxRef (currMB->b8mode[k]);
if( (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) && flag_mode )
{
currSE.len = 1;
readSyntaxElement_FLC(&currSE, dP->bitstream);
currSE.value1 = 1-currSE.value1;
}
else
{
currSE.value2 = LIST_1;
dP->readSyntaxElement (&currSE,img,inp,dP);
}
refframe = currSE.value1;

for (j=j0; j<j0+step_v0;j++)
{
for (i=i0; i<i0+step_h0;i++)
{
dec_picture->ref_idx[LIST_1][img->block_x + i][img->block_y + j] = refframe;
}
}
}
}
}
}
else
{
for (j0=0; j0<4; j0+=step_v0)
{
for (i0=0; i0<4; i0+=step_h0)
{
k=2*(j0/2)+(i0/2);
if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0)
{
for (j=j0; j<j0+step_v0;j++)
for (i=i0; i<i0+step_h0;i++)
{
dec_picture->ref_idx[LIST_1][img->block_x + i][img->block_y + j] = 0;
}
}
}
}
}

//=====  READ FORWARD MOTION VECTORS =====
currSE.type = SE_MVD;
dP = &(currSlice->partArr[partMap[SE_MVD]]);

if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_se;
else                                                  currSE.reading = readMVD_CABAC;

for (j0=0; j0<4; j0+=step_v0)
for (i0=0; i0<4; i0+=step_h0)
{
k=2*(j0/2)+(i0/2);

if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && (currMB->b8mode[k] !=0))//has forward vector
{
mv_mode  = currMB->b8mode[k];
step_h   = BLOCK_STEP [mv_mode][0];
step_v   = BLOCK_STEP [mv_mode][1];

refframe = dec_picture->ref_idx[LIST_0][img->block_x+i0][img->block_y+j0];

for (j=j0; j<j0+step_v0; j+=step_v)
{
for (i=i0; i<i0+step_h0; i+=step_h)
{
j4 = img->block_y+j;
i4 = img->block_x+i;

// first make mv-prediction
SetMotionVectorPredictor (img, pmv, pmv+1, refframe, LIST_0, dec_picture->ref_idx, dec_picture->mv, i, j, 4*step_h, 4*step_v);

for (k=0; k < 2; k++)
{
TRACE_STRING("mvd_l0");

img->subblock_x = i; // position used for context determination
img->subblock_y = j; // position used for context determination
currSE.value2 = k<<1; // identifies the component; only used for context determination
dP->readSyntaxElement(&currSE,img,inp,dP);
curr_mvd = currSE.value1;

// vec就是运动矢量
// k为0的时候,表示运动矢量的x分量
// k为1的时候,表示运动矢量的y分量
vec=curr_mvd+pmv[k];           /* find motion vector */

// 下面这一小段代码就可以实现非skip形式的P宏块运动矢量的提取

fprintf(myNonSkipMV, "%-4d", vec);
controlFlag++;
if(0 == controlFlag % 8)
{
fprintf(myNonSkipMV, "\n\n");
controlFlag = 0;
}

for(ii=0;ii<step_h;ii++)
{
for(jj=0;jj<step_v;jj++)
{
dec_picture->mv  [LIST_0][i4+ii][j4+jj][k] = vec;
currMB->mvd      [LIST_0][j+jj] [i+ii] [k] = curr_mvd;
}
}
}
}
}
}
else if (currMB->b8mode[k=2*(j0/2)+(i0/2)]==0)
{
if (!img->direct_type)
{
int list_offset = ((img->MbaffFrameFlag)&&(currMB->mb_field))? img->current_mb_nr%2 ? 4 : 2 : 0;
int imgblock_y= ((img->MbaffFrameFlag)&&(currMB->mb_field))? (img->current_mb_nr%2) ? (img->block_y-4)/2:img->block_y/2 : img->block_y;

int refList = (co_located_ref_idx[LIST_0][img->block_x+i0][imgblock_y+j0]== -1 ? LIST_1 : LIST_0);
int ref_idx =  co_located_ref_idx[refList][img->block_x+i0][imgblock_y+j0];

if (ref_idx==-1)
{
for (j=j0; j<j0+step_v0; j++)
for (i=i0; i<i0+step_h0; i++)
{
dec_picture->ref_idx [LIST_1][img->block_x+i][img->block_y+j]=0;
dec_picture->ref_idx [LIST_0][img->block_x+i][img->block_y+j]=0;
j4 = img->block_y+j;
i4 = img->block_x+i;
for (ii=0; ii < 2; ii++)
{
dec_picture->mv [LIST_0][i4][j4][ii]=0;
dec_picture->mv [LIST_1][i4][j4][ii]=0;
}
}
}
else
{
int mapped_idx=-1, iref;
int j6;

for (iref=0;iref<min(img->num_ref_idx_l0_active,listXsize[LIST_0 + list_offset]);iref++)
{

if (dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][iref]==co_located_ref_id[refList][img->block_x+i0][imgblock_y+j0])
{
mapped_idx=iref;
break;
}
else //! invalid index. Default to zero even though this case should not happen
mapped_idx=INVALIDINDEX;
}

if (INVALIDINDEX == mapped_idx)
{
error("temporal direct error\ncolocated block has ref that is unavailable",-1111);
}

for (j=j0; j<j0+step_v0; j++)
for (i=i0; i<i0+step_h0; i++)
{
{
mv_scale = img->mvscale[LIST_0 + list_offset][mapped_idx];

dec_picture->ref_idx [LIST_0][img->block_x+i][img->block_y+j] = mapped_idx;
dec_picture->ref_idx [LIST_1][img->block_x+i][img->block_y+j] = 0;

j4 = img->block_y+j;
j6 = imgblock_y+j;
i4 = img->block_x+i;

for (ii=0; ii < 2; ii++)
{
//if (iTRp==0)
if (mv_scale == 9999 || listX[LIST_0+list_offset][mapped_idx]->is_long_term)
//                    if (mv_scale==9999 || Co_located->is_long_term)
{
dec_picture->mv  [LIST_0][i4][j4][ii]=co_located_mv[refList][i4][j6][ii];
dec_picture->mv  [LIST_1][i4][j4][ii]=0;
}
else
{
dec_picture->mv  [LIST_0][i4][j4][ii]=(mv_scale * co_located_mv[refList][i4][j6][ii] + 128 ) >> 8;
dec_picture->mv  [LIST_1][i4][j4][ii]=dec_picture->mv[LIST_0][i4][j4][ii] - co_located_mv[refList][i4][j6][ii];
}
}
}
}
}
}
}
}

//=====  READ BACKWARD MOTION VECTORS =====
currSE.type = SE_MVD;
dP          = &(currSlice->partArr[partMap[SE_MVD]]);

if (active_pps->entropy_coding_mode_flag == UVLC || dP->bitstream->ei_flag) currSE.mapping = linfo_se;
else                                                    currSE.reading = readMVD_CABAC;

for (j0=0; j0<4; j0+=step_v0)
{
for (i0=0; i0<4; i0+=step_h0)
{
k=2*(j0/2)+(i0/2);
if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && (currMB->b8mode[k]!=0))//has backward vector
{
mv_mode  = currMB->b8mode[k];
step_h   = BLOCK_STEP [mv_mode][0];
step_v   = BLOCK_STEP [mv_mode][1];

refframe = dec_picture->ref_idx[LIST_1][img->block_x+i0][img->block_y+j0];

for (j=j0; j<j0+step_v0; j+=step_v)
{
for (i=i0; i<i0+step_h0; i+=step_h)
{
j4 = img->block_y+j;
i4 = img->block_x+i;

// first make mv-prediction
SetMotionVectorPredictor (img, pmv, pmv+1, refframe, LIST_1, dec_picture->ref_idx, dec_picture->mv, i, j, 4*step_h, 4*step_v);

for (k=0; k < 2; k++)
{
TRACE_STRING("mvd_l1");

img->subblock_x = i; // position used for context determination
img->subblock_y = j; // position used for context determination
currSE.value2   = (k<<1) +1; // identifies the component; only used for context determination
dP->readSyntaxElement(&currSE,img,inp,dP);
curr_mvd = currSE.value1;

vec=curr_mvd+pmv[k];           /* find motion vector */

for(ii=0;ii<step_h;ii++)
{
for(jj=0;jj<step_v;jj++)
{
dec_picture->mv  [LIST_1][i4+ii][j4+jj][k] = vec;
currMB->mvd      [LIST_1][j+jj] [i+ii] [k] = curr_mvd;
}
}
}
}
}
}
}
}
// record reference picture Ids for deblocking decisions

for(i4=img->block_x;i4<(img->block_x+4);i4++)
for(j4=img->block_y;j4<(img->block_y+4);j4++)
{
if(dec_picture->ref_idx[LIST_0][i4][j4]>=0)
dec_picture->ref_pic_id[LIST_0][i4][j4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_0 + list_offset][dec_picture->ref_idx[LIST_0][i4][j4]];
else
dec_picture->ref_pic_id[LIST_0][i4][j4] = INT64_MIN;
if(dec_picture->ref_idx[LIST_1][i4][j4]>=0)
dec_picture->ref_pic_id[LIST_1][i4][j4] = dec_picture->ref_pic_num[img->current_slice_nr][LIST_1 + list_offset][dec_picture->ref_idx[LIST_1][i4][j4]];
else
dec_picture->ref_pic_id[LIST_1][i4][j4] = INT64_MIN;
}
}

       上面代码就可以提取skip形式的P宏块的运动矢量.

 

       经与H.264visa对比后发现,上述代码处提取的运动矢量与H.264visa提取的运动矢量完全一致. OK. 最后强调一句:实际运动矢量是上述运动矢量除以4.

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: