如何利用JM8.6解码器提取码流中P帧宏块(第一个4*4块)的运动矢量(考虑B帧,设x264编码的12帧为IDR BBPBBPBBPBP)

来源:互联网 发布:软件测试行业前景 编辑:程序博客网 时间:2024/05/22 01:59

      前面已经讨论过,在没有B帧的情况下如何提取P帧的运动矢量,没有考虑B帧. 现在考虑P帧,假设视频有12帧,x264对其进行编码,编码的帧结构为:IDR BBPBBPBBPBP. 故共有4个P帧.  (视频格式是qcif格式)

 

      我们知道,在H.264中,P帧中可以有I宏块,本人为了便于数据处理,认为I宏块也有运动矢量,其值为零.  与MPEG2不同的是:在H.264中,一个宏块可以继续进行分块,所以并不是一个宏块对应一个运动矢量,而是每个分块都有各自的运动的矢量,为了方便起见,仅仅考虑提取宏块最左上角的那个4*4块对应的运动矢量.

 

      如此一来,4个P帧总共的宏块个数为99 * 4 = 396个, 对应396个运动矢量. 下面来看看重要的read_one_macroblock函数:

// 用x264编码12帧 宏块总数为99 * 12 = 1188// 编码的帧结构为:IDR BBPBBPBBPBP// 1个I帧,7个B帧,共4个P帧int read_one_macroblock(struct img_par *img,struct inp_par *inp){  // 12帧共1188个宏块,此处被调用1188次  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;  }// I帧内的宏块到此为止  // 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  {    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;          }        }      }    }  }    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))  {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);  // 此处被调用1188次  // 下面这个部分是提取运动矢量的重头戏  // 1188个宏块如何分配呢?  // 1188 = 325 + 78 + 785  if (IS_DIRECT (currMB) && img->cod_counter >= 0)  {// 此处被调用325次// 由于涉及到B宏块,所以,不理它    currMB->cbp = 0;    reset_coeffs();    if (active_pps->entropy_coding_mode_flag ==CABAC)      img->cod_counter=-1;        return DECODE_MB;  }  if (IS_COPY (currMB)) //keep last macroblock  {// IS_COPY表示skip形式的P宏块(不表示skip形式的B宏块)// 用H.264visa观察到4个P帧共有78个skip形式的P宏块    // 此处刚好被调用78次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;    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宏块的运动矢量为零  fprintf(myMV, "%-4d %-4d ", 0, 0);      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(myMV, "%-4d %-4d ", pmv[0], pmv[1]);        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;  }// skip形式的P宏块结束    if(currMB->mb_type!=IPCM)  { // 有785个宏块进入到此处,此处被调用785次    // intra prediction modes for a macroblock 4x4 **********************************************    read_ipred_modes(img,inp);        // read inter frame vector data *********************************************************    if (IS_INTERMV (currMB))    {            // 此处被调用632次      // 下面这个是一个极为关键的函数  // B宏块和P宏块都有可能进入该函数  // 如果只提取P帧的运动矢量,则要加限制      readMotionInfoFromNAL (img, inp);    }// 下面这些else if是本人加的,目的是为了方便数据处理    // 认为P帧中I宏块的运动矢量为(0, 0),便于统一操作// 785 - 632 = 153, 153 = 99 + 37 + 17else if(img->type == I_SLICE){ // 此处被调用99次,刚好是I帧中的宏块数NULL; // 空语句}else if(img->type == P_SLICE){ // 此处被调用37次// 4个P帧的I宏块刚好37个    // 为了数据对齐,认为P帧中I宏块的运动矢量为零fprintf(myMV, "%-4d %-4d ", 0, 0);}else if(img->type == B_SLICE){ // 此处被调用17次    // 7个B帧的B_Direct_16x16宏块刚好17个NULL;}    // 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;}

       接着看重要的函数readMotionInfoFromNAL函数:

void readMotionInfoFromNAL (struct img_par *img, struct inp_par *inp){  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=curr_mvd+pmv[k];           /* find motion vector */                        // 取每个宏块的最左上角的那个4 * 4块的运动矢量  // 故用controlFlag <= 2 来限制x分量和y分量  // 由于B宏块也会进入到这里,所以要用P_SLICE限制  // skip形式的P宏块不会进入到这里来,所以不用担心  controlFlag++;  if(controlFlag <= 2 && img->type == P_SLICE)  {  //another++;      //printf("********%d another\n", another);  fprintf(myMV, "%-4d ", vec);  }                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;    }}

     

       经验证,上面提取的运动矢量的结果和H.264visa提取的运动矢量的结果完全一致. OK, 这样就实现了对码流中P帧运动矢量的提取. 最后强调一句:实际运动矢量是上述运动矢量除以4.

原创粉丝点击