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

      前面已经讨论过,在没有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 + 17
	else 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.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值