h.264直接預測

直接預測是B幀上一種獨有的預測方式,其中直接預測又分爲兩種模式: 時域直接模式(temporal direct)、空域直接模式(spatial direct)。html

在分析這兩種模式以前,有一個前提概念須要瞭解:共同位置4x4子宏塊分割塊(co-located 4x4 sub-macroblock partitions),下面簡稱爲co-located。api

共同位置4x4子宏塊分割塊,故名思義,該塊大小爲4x4。co-located的主要功能是獲得出該4x4塊的運動向量以及參考幀,以供後面的直接預測作後續處理,若是當前宏塊進行的是直接預測,不管時域或空域,都會用到該co-located,所以須要先求出該4x4co-located的具體位置。app

 

co-located的定位

1. 定位co-located所在圖像

要求co-located的位置,首先須要知道co-located所在的圖像colPic的位置,colPic能夠肯定在當前圖像的第一個後向參考圖像RefPicList1[ 0 ]內,可是colPic能夠爲幀或場,這取決於當期圖像與參考圖像,是以幀圖像進行編碼,仍是以場圖像進行編碼,或者以互補場對(宏塊級幀場自適應)方式進行編碼。ide

  • 第一項:field_pic_flag表示當前圖像是以幀仍是場方式進行編碼
  • 第二項:表明RefPicList1[0]的編碼方式是幀、場、互補場對(兩個場)
  • 第三項:mb_field_decoding_flag表明當前宏塊對是以幀、場方式進行編碼(前提條件是當前圖像是以幀方式進行編碼,也只有當前圖像選擇了幀編碼,才能選擇宏塊對(宏塊幀場自適應)的編碼方式)
  • 第四項:

    $\begin{align*}
    topAbsDiffPOC &= |DiffPicOrderCnt( firstRefPicL1Top, CurrPic )|\\
    bottomAbsDiffPOC &= |DiffPicOrderCnt( firstRefPicL1Bottom, CurrPic )|
    \end{align*}$this

    添加這些條件是爲了在採用宏塊級幀場自適編碼方式時,應選擇距離當前圖像最近的頂場或底場做爲col_Pic編碼

  • 第五項:col_Pic的取值,firstRefPicL1Top 和firstRefPicL1Bottom 分別爲RefPicList1[ 0 ]中的頂場和底場

注:其實第二項RefPicList1[ 0 ]是一個被動選項,由於它是根據當前圖像的編碼方式是幀、場或宏塊幀場自適應決定的,若是當前圖像是場,那麼RefPicList1[ 0 ]就有多是已解碼的場或者以解碼幀中的一場;若是當前圖像是幀(非MBAFF),那麼RefPicList1[ 0 ]就是幀;若是當前宏塊是幀而且爲MBAFF,那麼RefPicList1[ 0 ]就是一個互補場對(兩個場能夠組成一個幀)spa

 

2. 獲得co-located在colPic內的位置

實際上,若是獲得了colPic,就能夠經過當前宏塊的16個4x4塊的絕對位置(以4x4塊爲單位相對於圖像左上角(0,0)的絕對位置( opic_block_x,opic_block_y)),獲得co-located在colPic的位置。3d

  • 若是當前圖像爲幀,colPic爲場,則co-located爲(opic_block_x,opic_block_y>>1)
  • 若是當前圖像爲場,colPic爲幀,則co-located爲(opic_block_x,opic_block_y<<1)
  • 若是當前圖像與colPic同爲幀或場,則co-located爲(opic_block_x,opic_block_y)

(注:像在jm18.6中,實際計算時,不會出現當前圖像爲場,colPic爲幀的狀況,由於場的參考圖像都會被分爲場後加入參考圖像隊列,因此最終計算時也會先根據當前場的是頂場或底場挑出參考幀中對應的場做爲colPic )code

 

在標準中,先定位co-located所在宏塊mbAddrCol,而後再定位co-located在該宏塊內的地址(xcol,yM)。因爲採用了不一樣於上述的4x4塊定位方法,因此計算方式略複雜,可是獲得的結果是同樣的,最終會定位到同一個co-locatedorm

$\begin{align*}
mbAddrCol1 &= 2 \times PicWidthInMbs \times( CurrMbAddr / PicWidthInMbs ) +( CurrMbAddr \ \% \ PicWidthInMbs ) + PicWidthInMbs \times ( yCol / 8 ) \\
mbAddrCol2 &= 2 \times CurrMbAddr + ( yCol / 8 ) \\
mbAddrCol3 &= 2 \times CurrMbAddr + bottom\_field\_flag \\
mbAddrCol4 &= PicWidthInMbs \times( CurrMbAddr / ( 2 \times PicWidthInMbs ) ) +( CurrMbAddr\ \% \ PicWidthInMbs ) \\
mbAddrCol5 &= CurrMbAddr / 2 \\
mbAddrCol6 &= 2 \times ( CurrMbAddr / 2 ) + ( ( topAbsDiffPOC < bottomAbsDiffPOC ) ? 0 : 1 ) \\
mbAddrCol7 &= 2 \times( CurrMbAddr / 2 ) + ( yCol / 8 )
\end{align*}$

 

(FAQ:爲什麼表中沒有FRM與AFRM配對?由於一個sps內只能定義爲FRM或者AFRM(MBAFF),在一個序列內二者是不可能共存的;爲什麼表中能夠有FRM與FLD共存?由於sps能夠定義PAFF(圖像幀場自適應))

 

  • 第一項:PicCodingStruct( CurrPic ),當前圖像的編碼方式
  • 第二項:PicCodingStruct( colPic ),colPic的編碼方式
  • 第三項:mbAddrX,當colPic爲AFRM(宏塊幀場自適應時),該項是用於定位colPic內地址爲mbAddrX的宏塊對,並用該宏塊判斷第五項fieldDecodingFlagX,即該宏塊對是用場編碼仍是幀編碼方式
  • 第四項:mb_field_decoding_flag,若是當前圖像的編碼方式是AFRM,該項用於判斷當前宏塊對是幀編碼仍是場編碼方式
  • 第五項:fieldDecodingFlagX,若是colPic的編碼方式是AFRM,該項用於判斷mbAddrX所在的宏塊對是幀編碼仍是場編碼方式
  • 第六項:mbAddrCol,co-located所在的宏塊在colPic內的地址,(注:涉及到AFRM的圖像都會被當作互補場對來處理,即AFRM幀,而不是colPic)
  • 第七項:yM,co-located相對於其所在宏塊的地址(xCol, yM),單位爲像素,即第一個4x4塊爲(0,0),最後一個爲(12,12),(注:當前4x4塊相對於其所在宏塊的地址爲(xCol,yCol))
  • 第八項:VertMvScale,代表CurrPic與colPic的幀場對應關係

 

另外,爲了減小計算量,還能夠設定direct_8x8_inference_flag等於1,這樣會致使8x8塊共用一個4x4的co-located的運動向量,共用方式爲一個宏塊的4個8x8塊分別只用該宏塊4個角的4x4塊做爲co-located

 

得到co-located的運動向量與參考幀

  • 若是co-located是幀內預測方式編碼,那麼將沒法得到運動向量與參考幀,mvCol = 0,refIdxCol = -1
  • 若是co-located是幀間預測編碼方式,而且存在前向參考幀,那麼mvCol將是co-located的前向運動向量,refIdxCol是co-located所在的8x8塊中的前向參考索引
  • 若是co-located是幀間預測編碼方式,而且只存在後向參考幀,那麼mvCol將是co-located的後向運動向量,refIdxCol是co-located所在的8x8塊中的後向參考索引

(注:標準規定參考圖像選擇的最小單位爲8x8塊,也就是說8x8塊中的4個4x4塊共享一個參考圖像索引,請參考h.264語法結構分析中的ref_idx_l0以及ref_idx_l1關鍵字)

 

 

時域直接模式(temporal direct)

該模式是基於下圖求出當前4x4塊的先後向mvL0與mvL1,以及前向參考幀List0 reference的索引

已知的變量有:

  1. 後向參考圖像List 1 reference (refPicList1[0])及其索引0
  2. 在計算co-located後獲得的mvCol(mvCol須要根據VertMvScale進行調整,乘或除2),以及參考圖像refColList0[refIdxCol](即List 0 reference)
  3. td與tb爲圖像之間的POC距離,既然List 0 reference、Current B、List 1 reference 已經知道,那麼就容易得出td與tb的值

未知的變量有:

  1. List 0 reference的在當前參考圖像列表中的索引
  2. 先後向運動向量mvL0與mvL1

求解方法:

  1. List 0 reference的索引,該索引是參考圖像列表中圖像List 0 reference所在的最小索引值(這部分因爲jm18.6中對mbaff採用了獨立互補場對參考列表,因此看起來更簡單一點,而標準是從refPicList0參考列表開始,而後結合VertMvScale進行推導,看起來比較繁瑣,但其實獲得的結果是同樣的)。
  2. mvL1 = mvCol/td*(td - tb)
  3. mvL0 = mvCol - mvL1    (忽略mv方向)

因爲這些在標準(8.4.1.2.3)中講的都很是細緻,因此這裏簡要說明一下而已。

 

空域直接模式(spatial direct)

空域模式基於一種假設:當前編碼宏塊與其相鄰宏塊都向着同一個方向運動,你們有着相似的運動向量與參考幀(以下圖)。在這種假設前提上,空域模式主要思想爲採用相鄰塊來對當前宏塊的參考索引以及運動向量進行預測。因爲標準中8.4.1.3有很是詳細的描述,因此在此略過。

可是上述假設也頗有可能不成立,有可能當前宏塊的相鄰塊都是運動的,但當前宏塊是靜止的(以下圖)。好比說當前宏塊是背景的一部分,而相鄰塊則是移動着的前景。這時候就須要判斷當前宏塊是不是運動的,以獲得更準確的空域預測,co-located在這裏就是用來判斷當前宏塊是不是運動宏塊的。若是co-located的mvCol[0]與mvCol[1]能保證在某個範圍以內,則代表當前宏塊爲靜止宏塊,那麼將把當前宏塊的mvL0與mvL1賦值爲0,具體在標準8.4.1.2.2中描述得至關詳細,不做細述。

 

jm18.6 mv_direct.c

 /*!
  *************************************************************************************
  * \file mv_direct.c
  *
  * \brief
  *    Direct Motion Vector Generation
  *
  * \author
  *    Main contributors (see contributors.h for copyright, address and affiliation details)
  *      - Alexis Michael Tourapis         <alexismt@ieee.org>
  *
  *************************************************************************************
 */
 
 #include "contributors.h"
 
 #include <math.h>
 #include <limits.h>
 #include <time.h>
 
 #include "global.h"
 
 #include "image.h"
 #include "mv_search.h"
 #include "refbuf.h"
 #include "memalloc.h"
 #include "mb_access.h"
 #include "macroblock.h"
 #include "mc_prediction.h"
 #include "conformance.h"
 #include "mode_decision.h"
 
 /*!
  ************************************************************************
  * \brief
  *    Calculate Temporal Direct Mode Motion Vectors
  ************************************************************************
  */
 void Get_Direct_MV_Temporal (Macroblock *currMB)
 {
   Slice *currSlice = currMB->p_Slice; 
   int   block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
   MotionVector *****all_mvs;
   int   mv_scale;
   int refList;
   int ref_idx;
   VideoParameters *p_Vid = currMB->p_Vid;
   int list_offset = currMB->list_offset;//若是當前currSlice->mb_aff_frame_flag 且 currMB->mb_field ,list_offset>0
 
   StorablePicture **list1 = currSlice->listX[LIST_1 + list_offset];
 
   PicMotionParams colocated;
 
   //temporal direct mode copy from decoder
   for (block_y = 0; block_y < 4; block_y++)
   {
     pic_block_y  = currMB->block_y + block_y;
     opic_block_y = (currMB->opix_y >> 2) + block_y;
 
     for (block_x = 0; block_x < 4; block_x++)
     {
       pic_block_x  = currMB->block_x + block_x;
       opic_block_x = (currMB->pix_x>>2) + block_x;
 
       all_mvs = currSlice->all_mv;
       if (p_Vid->active_sps->direct_8x8_inference_flag)
       {
         if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
           colocated = list1[0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(opic_block_y)][RSD(opic_block_x)];
         else
           colocated = list1[0]->mv_info[RSD(opic_block_y)][RSD(opic_block_x)];
         if(currSlice->mb_aff_frame_flag && currMB->mb_field && currSlice->listX[LIST_1][0]->coded_frame)
         {//mbaff場宏塊
           int iPosBlkY;
           if(currSlice->listX[LIST_1][0]->motion.mb_field[currMB->mbAddrX] )
               //當前宏塊是mbaff且爲場編碼,參考幀宏塊爲場編碼,不過由於此處計算ref_pic用的是frame,即一個場宏塊對應兩個幀宏塊
               //場宏塊>>2後*8,能夠對比下面幀宏塊>>3後再*8
               //>>2表明一個場宏塊,
               //*8表明宏塊對(兩個幀宏塊),
               //*4表明選擇對應宏塊(頂宏塊或者底宏塊其中之一(field重建回frame時,對於宏塊的mv_info,是以宏塊對方式組建的?)),
               //&3表明4x4子塊
               //另外因爲每個8x8塊對應一個參考幀因此最後也有RSD(opic_block_x)
             iPosBlkY = (opic_block_y>>2)*8+4*(currMB->mbAddrX&1)+(opic_block_y&0x03);
           else
               //由於當前是場(mb_field)?而下面參考幀採用的是幀,則表明field->frame,因此*2
             iPosBlkY = RSD(opic_block_y)*2;
 
           //因爲標準規定(8.4.1.2.2最後一段)在colocated中應該在其所在的8x8分割塊中選取參考幀,因此須要進行如下步驟
           if(colocated.ref_idx[LIST_0]>=0)//ref_idx>=0說明有前/後向參考幀,可是下面還須要根據當前宏塊與colpic進行精肯定位(在8x8分割塊中選取某塊的參考幀)
             colocated.ref_pic[LIST_0] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_0];
           if(colocated.ref_idx[LIST_1]>=0)
             colocated.ref_pic[LIST_1] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_1];
         }        
       }
       else
       {
         if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
           colocated = list1[0]->JVmv_info[currMB->p_Slice->colour_plane_id][opic_block_y][opic_block_x];
         else
           colocated = list1[0]->mv_info[opic_block_y][opic_block_x];
       }
       if(currSlice->mb_aff_frame_flag)
       {
         if(!currMB->mb_field && ((currSlice->listX[LIST_1][0]->coded_frame && currSlice->listX[LIST_1][>motion.mb_field[currMB->mbAddrX]) ||
           (!currSlice->listX[LIST_1][0]->coded_frame)))
         {//mbaff幀宏塊
           if (iabs(p_Vid->enc_picture->poc - currSlice->listX[LIST_1+4][0]->poc)> iabs(p_Vid->enc_picture->poc -rSlice->listX[LIST_1+2][0]->poc) )
           {
             if ( p_Vid->active_sps->direct_8x8_inference_flag)
             {
               if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
                 colocated = currSlice->listX[LIST_1+2][0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(c_block_y)>>1][RSD(opic_block_x)];
               else
                 colocated = currSlice->listX[LIST_1+2][0]->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)];
             }
             else
             { 
               if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
                 colocated = currSlice->listX[LIST_1+2][0]->JVmv_info[currMB->p_Slice->colour_plane_id][(c_block_y)>>1][(opic_block_x)];
               else
                 colocated = currSlice->listX[LIST_1+2][0]->mv_info[(opic_block_y)>>1][opic_block_x];
             }
             if(currSlice->listX[LIST_1][0]->coded_frame)
             {//幀宏塊,因此下面>>3後再*8,能夠對比上面場宏塊>>2後再*8
               int iPosBlkY = (RSD(opic_block_y)>>3)*8 + ((RSD(opic_block_y)>>1) & 0x03);
               if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0])
                 colocated.ref_pic[LIST_0] = currSlice->listX[LIST_1+2][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[T_0];
               if(colocated.ref_idx[LIST_1] >=0) // && !colocated.ref_pic[LIST_1])
                 colocated.ref_pic[LIST_1] = currSlice->listX[LIST_1+2][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[T_1];
             }
           }
           else
           {
             if (p_Vid->active_sps->direct_8x8_inference_flag )
             {
               if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
                 colocated = currSlice->listX[LIST_1+4][0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(c_block_y)>>1][RSD(opic_block_x)];
               else
                 colocated = currSlice->listX[LIST_1+4][0]->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)];
 
             }
             else
             {
               if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444)
                 colocated = currSlice->listX[LIST_1+4][0]->JVmv_info[currMB->p_Slice->colour_plane_id][(c_block_y)>>1][opic_block_x];
               else
                 colocated = currSlice->listX[LIST_1+4][0]->mv_info[(opic_block_y)>>1][opic_block_x];
             }
             if(currSlice->listX[LIST_1][0]->coded_frame)
             {
               int iPosBlkY = (RSD(opic_block_y)>>3)*8 + ((RSD(opic_block_y)>>1) & 0x03)+4;
               if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0])
                 colocated.ref_pic[LIST_0] = currSlice->listX[LIST_1+4][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[T_0];
               if(colocated.ref_idx[LIST_1] >=0)// && !colocated.ref_pic[LIST_1])
                 colocated.ref_pic[LIST_1] = currSlice->listX[LIST_1+4][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[T_1];
             }
           }
         }
       }
       else if(!p_Vid->active_sps->frame_mbs_only_flag && !currSlice->structure && !currSlice->listX[LIST_1][>coded_frame)
       {//圖像級幀場自適應幀圖像編碼(即list1[0]有可能爲場編碼)
         if (iabs(p_Vid->enc_picture->poc - list1[0]->bottom_field->poc)> iabs(p_Vid->enc_picture->poc -list1[>top_field->poc) )
         {
           colocated = p_Vid->active_sps->direct_8x8_inference_flag ? 
             list1[0]->top_field->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)] : list1[0]->top_field->mv_info[(c_block_y)>>1][opic_block_x];
         }
         else
         {
           colocated = p_Vid->active_sps->direct_8x8_inference_flag ? 
             list1[0]->bottom_field->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)] : list1[0]->bottom_field->mv_info[(c_block_y)>>1][opic_block_x];
         }
       }
       else if(!p_Vid->active_sps->frame_mbs_only_flag && currSlice->structure && list1[0]->coded_frame)
       {//場圖像編碼
         int iPosBlkY; 
         int currentmb = 2*(list1[0]->size_x>>4) * (opic_block_y >> 2)+ (opic_block_x>>2)*2 + ((c_block_y>>1) & 0x01);
         if(currSlice->structure!=list1[0]->structure)
         {
           if (currSlice->structure == TOP_FIELD)
           {
             colocated = p_Vid->active_sps->direct_8x8_inference_flag ? 
               list1[0]->frame->top_field->mv_info[RSD(opic_block_y)][RSD(opic_block_x)] : list1[>frame->top_field->mv_info[opic_block_y][opic_block_x];
           }
           else
           {
             colocated = p_Vid->active_sps->direct_8x8_inference_flag ? 
               list1[0]->frame->bottom_field->mv_info[RSD(opic_block_y)][RSD(opic_block_x)] : list1[>frame->bottom_field->mv_info[opic_block_y][opic_block_x];
           }
         }
 
         if(!currSlice->listX[LIST_1][0]->frame->mb_aff_frame_flag || !list1[0]->frame->motion.mb_field[currentmb])
           iPosBlkY = 2*(RSD(opic_block_y));
         else
           iPosBlkY = (RSD(opic_block_y)>>2)*8 + (RSD(opic_block_y) & 0x03)+4*(currSlice->structure == BOTTOM_FIELD);
         if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0])
           colocated.ref_pic[LIST_0] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_0];
         if(colocated.ref_idx[LIST_1] >=0)// && !colocated.ref_pic[LIST_1])
           colocated.ref_pic[LIST_1] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_1];
       }
       //最後剩下的是全序列採用幀圖像編碼(frame_mbs_only_flag = 1),這樣的話colocated._pic確定是存在的,而且不用進行幀場轉換,也就是採用原來的就能夠,所以不用從新賦值
       //colocated在開頭判斷direct_8x8_inference_flag的兩個分支處便可得到
 
       refList = ((colocated.ref_idx[LIST_0] == -1 || (p_Vid->view_id && colocated.ref_idx[LIST_0]==list1[0]->ref_pic_na[)? LIST_1 : LIST_0);
       ref_idx = colocated.ref_idx[refList];
 
       // next P is intra mode
       if (ref_idx == -1 || (p_Vid->view_id && ref_idx==list1[0]->ref_pic_na[refList]))
       {
         all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
         all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
         currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = 0;
         currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = 0;
         currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
       }
       // next P is skip or inter mode
       else
       {
         int mapped_idx=INVALIDINDEX;
         int iref;
         if (colocated.ref_pic[refList] == NULL) 
         {
            printf("invalid index found\n");
         }
         else
         {    //獲得前向參考幀ref0,即下面的mapped_idx
         //Let refIdxL0Frm be the lowest valued reference index in the current reference picture list RefPicList0 that 
         //references the frame or complementary field pair that contains the field refPicCol
           if( (currSlice->mb_aff_frame_flag && ( (currMB->mb_field && colocated.ref_pic[List]->structure==FRAME) ||          //currSlice :mbaff & mb_field, ref_pic :frame
             (!currMB->mb_field && colocated.ref_pic[refList]->structure!=FRAME)))                                             //currSlice :mb_frame        , ref_pic :field
             (!currSlice->mb_aff_frame_flag && ((currSlice->structure==FRAME && colocated.ref_pic[List]->structure!=FRAME)||   //currSlice :frame only       , ref_pic :field
             (currSlice->structure!=FRAME && colocated.ref_pic[refList]->structure==FRAME)))                                   //currSlice :field           , ref_pic :frame
           {//該判斷條件表示currSlice與ref_pic用不一樣的幀場編碼方式
             //! Frame with field co-located
             for (iref = 0; iref < imin(currSlice->num_ref_idx_active[LIST_0], currSlice->listXsize[LIST_0 + list_offset]); f++)
             {
               if (currSlice->listX[LIST_0 + list_offset][iref]->top_field == colocated.ref_pic[refList] ||
                 currSlice->listX[LIST_0 + list_offset][iref]->bottom_field == colocated.ref_pic[refList] ||
                 currSlice->listX[LIST_0 + list_offset][iref]->frame == colocated.ref_pic[refList] ) 
               {
                 if ((p_Vid->field_picture==1) && (currSlice->listX[LIST_0 + list_offset][iref]->structure != rSlice->structure))
                 {//currSlice :field       , ref_pic :frame  會進來這裏?
                   mapped_idx=INVALIDINDEX;
                 }
                 else
                 {
                   mapped_idx = iref;            
                   break;
                 }
               }
               else //! invalid index. Default to zero even though this case should not happen
                 mapped_idx=INVALIDINDEX;
             }
           }
           else
           {//currSlice 與 ref_pic 採用相同幀場編碼方式
             for (iref = 0; iref < imin(currSlice->num_ref_idx_active[LIST_0], currSlice->listXsize[LIST_0 + list_offset]);iref++)
             {
               if(currSlice->listX[LIST_0 + list_offset][iref] == colocated.ref_pic[refList])
               {
                 mapped_idx = iref;            
                 break;
               }
               else //! invalid index. Default to zero even though this case should not happen
               {
                 mapped_idx=INVALIDINDEX;
               }
             }
           }
         }
         if (mapped_idx != INVALIDINDEX)
         {
           MotionVector mv = colocated.mv[refList];
           mv_scale = currSlice->mvscale[LIST_0 + list_offset][mapped_idx];
 
           if((currSlice->mb_aff_frame_flag && !currMB->mb_field && colocated.ref_pic[refList]->structure!=FRAME) 
             (!currSlice->mb_aff_frame_flag && currSlice->structure==FRAME && colocated.ref_pic[List]->structure!=FRAME))
             mv.mv_y *= 2;
           else if((currSlice->mb_aff_frame_flag && currMB->mb_field && colocated.ref_pic[List]->structure==FRAME) ||
             (!currSlice->mb_aff_frame_flag && currSlice->structure!=FRAME && colocated.ref_pic[List]->structure==FRAME))
             mv.mv_y /= 2;
 
           //mvL0,mvL1
           if (mv_scale==9999)
           {
             // forward
             all_mvs[LIST_0][0][0][block_y][block_x] = mv;
             // backward
             all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
           }
           else
           {
             //mv_scale = DistScaleFactor (in function compute_colocated)
             // forward
             all_mvs[LIST_0][mapped_idx][0][block_y][block_x].mv_x = (short) ((mv_scale * mv.mv_x + 128) >> 8);
             all_mvs[LIST_0][mapped_idx][0][block_y][block_x].mv_y = (short) ((mv_scale * mv.mv_y + 128) >> 8);
             // backward
             all_mvs[LIST_1][         0][0][block_y][block_x].mv_x = (short) (((mv_scale - 256) * mv.mv_x + 128) >> 8);
             all_mvs[LIST_1][         0][0][block_y][block_x].mv_y = (short) (((mv_scale - 256) * mv.mv_y + 128) >> 8);
 
           }
           //refIdx0,refIdx1
           // Test Level Limits if satisfied.
           if ( out_of_bounds_mvs(p_Vid, &all_mvs[LIST_0][mapped_idx][0][block_y][block_x])|| out_of_bounds_mvs(p_Vid, &all_mvs[T_1][0][0][block_y][block_x]))
           {
             currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
             currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
             currSlice->direct_pdir[pic_block_y][pic_block_x] = -1;
           }
           else
           {
             currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = (char) mapped_idx;
             currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = 0;
             currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
           }
         }
         else
         {
           currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
           currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
           currSlice->direct_pdir[pic_block_y][pic_block_x] = -1;
         }
       }
 
       if (p_Vid->active_pps->weighted_bipred_idc == 1 && currSlice->direct_pdir[pic_block_y][pic_block_x] == 2)
       {
         int weight_sum, i;
         short l0_refX = currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0];
         short l1_refX = currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1];
         for (i=0;i< (p_Vid->active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++)
         {
           weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i];
           if (weight_sum < -128 ||  weight_sum > 127)
           {
             currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1;
             currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1;
             currSlice->direct_pdir   [pic_block_y][pic_block_x]         = -1;
             break;
           }
         }
       }
     }
   }
 }
 
 static inline void set_direct_references(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info)
 {
   if (mb->available)
   {
     char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx;
     *l0_rFrame  = ref_idx[LIST_0];
     *l1_rFrame  = ref_idx[LIST_1];
   }
   else
   {
     *l0_rFrame  = -1;
     *l1_rFrame  = -1;
   }
 }
 
 static void set_direct_references_mb_field(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info, Macroblock _data)
 {
   if (mb->available)
   {
     char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx;
     if (mb_data[mb->mb_addr].mb_field)
     {
       *l0_rFrame  = ref_idx[LIST_0];
       *l1_rFrame  = ref_idx[LIST_1];
     }
     else
     {
       *l0_rFrame  = (ref_idx[LIST_0] < 0) ? ref_idx[LIST_0] : ref_idx[LIST_0] * 2;
       *l1_rFrame  = (ref_idx[LIST_1] < 0) ? ref_idx[LIST_1] : ref_idx[LIST_1] * 2;
     }
   }
   else
   {
     *l0_rFrame  = -1;
     *l1_rFrame  = -1;
   }
 }
 
 static void set_direct_references_mb_frame(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info, Macroblock _data)
 {
   if (mb->available)
   {
     char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx;
     if (mb_data[mb->mb_addr].mb_field)
     {
       *l0_rFrame  = (ref_idx[LIST_0] >> 1);
       *l1_rFrame  = (ref_idx[LIST_1] >> 1);
     }
     else
     {
       *l0_rFrame  = ref_idx[LIST_0];
       *l1_rFrame  = ref_idx[LIST_1];
     }
   }
   else
   {
     *l0_rFrame  = -1;
     *l1_rFrame  = -1;
   }
 }
 
 static void test_valid_direct(Slice *currSlice, seq_parameter_set_rbsp_t *active_sps, char  *direct_ref_idx, short l0_refX, short refX, int pic_block_y, int pic_block_x)
 {
   int weight_sum, i;
   Boolean invalid_wp = FALSE;
   for (i=0;i< (active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++)
   {
     weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i];
     if (weight_sum < -128 ||  weight_sum > 127)
     {
       invalid_wp = TRUE;
       break;
     }
   }
   if (invalid_wp == FALSE)
     currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
   else
   {
     direct_ref_idx[LIST_0] = -1;
     direct_ref_idx[LIST_1] = -1;
     currSlice->direct_pdir[pic_block_y][pic_block_x] = -1;
   }
 }
 
 /*!
 *************************************************************************************
 * \brief
 *    Temporary function for colocated info when direct_inference is enabled. 
 *
 *************************************************************************************
 */
 int get_colocated_info(Macroblock *currMB, StorablePicture *list1, int i, int j)
 {
   if (list1->is_long_term)
     return 1;
   else
   {
     Slice *currSlice = currMB->p_Slice;
     VideoParameters *p_Vid = currMB->p_Vid;
     if( (currSlice->mb_aff_frame_flag) ||
       (!p_Vid->active_sps->frame_mbs_only_flag && ((!currSlice->structure && !list1->coded_frame) || (rSlice->structure!=list1->structure && list1->coded_frame))))
     {
       int jj = RSD(j);
       int ii = RSD(i);
       int jdiv = (jj>>1);
       int moving;
       PicMotionParams *fs = &list1->mv_info[jj][ii];
 
       if(currSlice->structure && currSlice->structure!=list1->structure && list1->coded_frame)
       {
          if(currSlice->structure == TOP_FIELD)
            fs = list1->top_field->mv_info[jj] + ii;
          else
            fs = list1->bottom_field->mv_info[jj] + ii;
       }
       else
       {
         if( (currSlice->mb_aff_frame_flag && ((!currMB->mb_field && list1->motion.mb_field[currMB->mbAddrX]) 
           (!currMB->mb_field && !list1->coded_frame))) 
           || (!currSlice->mb_aff_frame_flag))
         {
           if (iabs(p_Vid->enc_picture->poc - list1->bottom_field->poc)> iabs(p_Vid->enc_picture->poc -t1->top_field->poc) )
           {
             fs = list1->top_field->mv_info[jdiv] + ii;
           }
           else
           {
             fs = list1->bottom_field->mv_info[jdiv] + ii;
           }
         }
       }
       moving = !((((fs->ref_idx[LIST_0] == 0)
         &&  (iabs(fs->mv[LIST_0].mv_x)>>1 == 0)
         &&  (iabs(fs->mv[LIST_0].mv_y)>>1 == 0)))
         || ((fs->ref_idx[LIST_0] == -1)
         &&  (fs->ref_idx[LIST_1] == 0)
         &&  (iabs(fs->mv[LIST_1].mv_x)>>1 == 0)
         &&  (iabs(fs->mv[LIST_1].mv_y)>>1 == 0)));
       return moving;
     }
     else
     {
       PicMotionParams *fs = &list1->mv_info[RSD(j)][RSD(i)];
       int moving;
       if(currMB->p_Vid->yuv_format == YUV444 && !currSlice->P444_joined)
         fs = &list1->JVmv_info[(int)(p_Vid->colour_plane_id)][RSD(j)][RSD(i)];
       moving= !((((fs->ref_idx[LIST_0] == 0)
         &&  (iabs(fs->mv[LIST_0].mv_x)>>1 == 0)
         &&  (iabs(fs->mv[LIST_0].mv_y)>>1 == 0)))
         || ((fs->ref_idx[LIST_0] == -1)
         &&  (fs->ref_idx[LIST_1] == 0)
         &&  (iabs(fs->mv[LIST_1].mv_x)>>1 == 0)
         &&  (iabs(fs->mv[LIST_1].mv_y)>>1 == 0)));
 
       return moving;  
     }
   }
 }
 
 /*!
 *************************************************************************************
 * \brief
 *    Colocated info <= direct_inference is disabled. 
 *************************************************************************************
 */
 int get_colocated_info_4x4(Macroblock *currMB, StorablePicture *list1, int i, int j)
 {
   if (list1->is_long_term)
     return 1;
   else
   {
     PicMotionParams *fs = &list1->mv_info[j][i];
 
     int moving = !((((fs->ref_idx[LIST_0] == 0)
       &&  (iabs(fs->mv[LIST_0].mv_x)>>1 == 0)
       &&  (iabs(fs->mv[LIST_0].mv_y)>>1 == 0)))
       || ((fs->ref_idx[LIST_0] == -1)
       &&  (fs->ref_idx[LIST_1] == 0)
       &&  (iabs(fs->mv[LIST_1].mv_x)>>1 == 0)
       &&  (iabs(fs->mv[LIST_1].mv_y)>>1 == 0)));
 
     return moving;  
   }
 }
 
 /*!
 ************************************************************************
 * \brief
 *    Calculate Spatial Direct Mode Motion Vectors 
 ************************************************************************
 */
 void Get_Direct_MV_Spatial_Normal (Macroblock *currMB)
 {
   Slice *currSlice = currMB->p_Slice; 
   VideoParameters *p_Vid = currMB->p_Vid;
   PicMotionParams **mv_info = p_Vid->enc_picture->mv_info;
   char l0_refA, l0_refB, l0_refC;
   char l1_refA, l1_refB, l1_refC;
   char l0_refX,l1_refX;
   MotionVector pmvfw = zero_mv, pmvbw = zero_mv;
 
   int   block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
   MotionVector *****all_mvs;
   char  *direct_ref_idx;
   StorablePicture **list1 = currSlice->listX[LIST_1];
 
   PixelPos mb[4];  
   get_neighbors(currMB, mb, 0, 0, 16);
 
   set_direct_references(&mb[0], &l0_refA,  &l1_refA,  mv_info);
   set_direct_references(&mb[1], &l0_refB,  &l1_refB,  mv_info);
   set_direct_references(&mb[2], &l0_refC,  &l1_refC,  mv_info);
 
   l0_refX = (char) imin(imin((unsigned char) l0_refA, (unsigned char) l0_refB), (unsigned char) l0_refC);
   l1_refX = (char) imin(imin((unsigned char) l1_refA, (unsigned char) l1_refB), (unsigned char) l1_refC);
 
   if (l0_refX >= 0)
     currMB->GetMVPredictor (currMB, mb, &pmvfw, l0_refX, mv_info, LIST_0, 0, 0, 16, 16);
 
   if (l1_refX >= 0)
     currMB->GetMVPredictor (currMB, mb, &pmvbw, l1_refX, mv_info, LIST_1, 0, 0, 16, 16);
 
   if (l0_refX == -1 && l1_refX == -1)
   {
     for (block_y=0; block_y<4; block_y++)
     {
       pic_block_y  = currMB->block_y + block_y;
       for (block_x=0; block_x<4; block_x++)
       {
         pic_block_x  = currMB->block_x + block_x;
         direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
 
         currSlice->all_mv[LIST_0][0][0][block_y][block_x] = zero_mv;
         currSlice->all_mv[LIST_1][0][0][block_y][block_x] = zero_mv;
 
         direct_ref_idx[LIST_0] = direct_ref_idx[LIST_1] = 0;
 
         if (p_Vid->active_pps->weighted_bipred_idc == 1)
           test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, 0, 0, pic_block_y, pic_block_x);
         else
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
       }
     }
   }
   else if (l0_refX == 0 || l1_refX == 0)
   {
     int (*get_colocated)(Macroblock *currMB, StorablePicture *list1, int i, int j) = 
       p_Vid->active_sps->direct_8x8_inference_flag ? get_colocated_info : get_colocated_info_4x4;
 
     int is_moving_block;
     for (block_y = 0; block_y < 4; block_y++)
     {
       pic_block_y  = currMB->block_y + block_y;
       opic_block_y = (currMB->opix_y >> 2) + block_y;
 
       for (block_x=0; block_x<4; block_x++)
       {
         pic_block_x    = currMB->block_x + block_x;
         direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
         opic_block_x   = (currMB->pix_x >> 2) + block_x;
 
         all_mvs = currSlice->all_mv;
         is_moving_block = (get_colocated(currMB, list1[0], opic_block_x, opic_block_y) == 0);
 
         if (l0_refX < 0)
         {
           all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
           direct_ref_idx[LIST_0] = -1;
         }
         else if ((l0_refX == 0) && is_moving_block)
         {
           all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
           direct_ref_idx[LIST_0] = 0;
         }
         else
         {
           all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw;
           direct_ref_idx[LIST_0] = (char)l0_refX;
         }
         
         if (l1_refX < 0)
         {
           all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
           direct_ref_idx[LIST_1] = -1;
         }
         else if((l1_refX == 0) && is_moving_block)
         {
           all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
           direct_ref_idx[LIST_1] = 0;
         }
         else
         {
           all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw;
           direct_ref_idx[LIST_1] = (char)l1_refX;
         }
 
         if      (direct_ref_idx[LIST_1] == -1)
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 0;
         else if (direct_ref_idx[LIST_0] == -1)
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 1;
         else if (p_Vid->active_pps->weighted_bipred_idc == 1)
           test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x);
         else
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
       }
     }
   }
   else
   {
     for (block_y=0; block_y<4; block_y++)
     {
       pic_block_y  = currMB->block_y + block_y;
 
       for (block_x=0; block_x<4; block_x++)
       {
         pic_block_x  = currMB->block_x + block_x;
         direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
 
         all_mvs = currSlice->all_mv;
 
         if (l0_refX > 0)
         {
           all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw;
           direct_ref_idx[LIST_0]= (char)l0_refX;          
         }
         else
         {
           all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
           direct_ref_idx[LIST_0]=-1;
         }
 
         if (l1_refX > 0)
         {
           all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw;
           direct_ref_idx[LIST_1] = (char)l1_refX;
         }
         else
         {
           all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
           direct_ref_idx[LIST_1] = -1;
         }
 
         if      (direct_ref_idx[LIST_1] == -1)
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 0;
         else if (direct_ref_idx[LIST_0] == -1)
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 1;
         else if (p_Vid->active_pps->weighted_bipred_idc == 1)
           test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x);
         else
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
       }
     }
   }
 }
 
 
 /*!
 ************************************************************************
 * \brief
 *    Calculate Spatial Direct Mode Motion Vectors 
 ************************************************************************
 */
 void Get_Direct_MV_Spatial_MBAFF (Macroblock *currMB)
 {
   char l0_refA, l0_refB, l0_refC;
   char l1_refA, l1_refB, l1_refC;
   char l0_refX,l1_refX;
   MotionVector pmvfw = zero_mv, pmvbw = zero_mv;
 
   int   block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y;
   MotionVector *****all_mvs;
   char  *direct_ref_idx;
   int is_moving_block;
   Slice *currSlice = currMB->p_Slice;
   VideoParameters *p_Vid = currMB->p_Vid;
   PicMotionParams **mv_info = p_Vid->enc_picture->mv_info;
   StorablePicture **list1 = currSlice->listX[LIST_1 + currMB->list_offset];
 
   int (*get_colocated)(Macroblock *currMB, StorablePicture *list1, int i, int j) = 
     p_Vid->active_sps->direct_8x8_inference_flag ? get_colocated_info : get_colocated_info_4x4;
 
   PixelPos mb[4];  
   get_neighbors(currMB, mb, 0, 0, 16);
 
 
   if (currMB->mb_field)
   {
     set_direct_references_mb_field(&mb[0], &l0_refA, &l1_refA, mv_info, p_Vid->mb_data);
     set_direct_references_mb_field(&mb[1], &l0_refB, &l1_refB, mv_info, p_Vid->mb_data);
     set_direct_references_mb_field(&mb[2], &l0_refC, &l1_refC, mv_info, p_Vid->mb_data);
   }
   else
   {
     set_direct_references_mb_frame(&mb[0], &l0_refA, &l1_refA, mv_info, p_Vid->mb_data);
     set_direct_references_mb_frame(&mb[1], &l0_refB, &l1_refB, mv_info, p_Vid->mb_data);
     set_direct_references_mb_frame(&mb[2], &l0_refC, &l1_refC, mv_info, p_Vid->mb_data);
   }
 
   l0_refX = (char) imin(imin((unsigned char) l0_refA, (unsigned char) l0_refB), (unsigned char) l0_refC);
   l1_refX = (char) imin(imin((unsigned char) l1_refA, (unsigned char) l1_refB), (unsigned char) l1_refC);
 
   if (l0_refX >=0)
     currMB->GetMVPredictor (currMB, mb, &pmvfw, l0_refX, mv_info, LIST_0, 0, 0, 16, 16);
 
   if (l1_refX >=0)
     currMB->GetMVPredictor (currMB, mb, &pmvbw, l1_refX, mv_info, LIST_1, 0, 0, 16, 16);
 
   for (block_y=0; block_y<4; block_y++)
   {
     pic_block_y  = currMB->block_y + block_y;
     opic_block_y = (currMB->opix_y >> 2) + block_y;
 
     for (block_x=0; block_x<4; block_x++)
     {
       pic_block_x  = currMB->block_x + block_x;
       direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x];
       opic_block_x = (currMB->pix_x >> 2) + block_x;
       is_moving_block = (get_colocated(currMB, list1[0], opic_block_x, opic_block_y) == 0);
 
       all_mvs = currSlice->all_mv;
 
       if (l0_refX >=0)
       {
         if (!l0_refX  && is_moving_block)
         {
           all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
           direct_ref_idx[LIST_0] = 0;
         }
         else
         {
           all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw;
           direct_ref_idx[LIST_0] = (char)l0_refX;
         }
       }
       else
       {
         all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv;
         direct_ref_idx[LIST_0] = -1;
       }
 
       if (l1_refX >=0)
       {
         if(l1_refX==0 && is_moving_block)
         {
           all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
           direct_ref_idx[LIST_1] = (char)l1_refX;
         }
         else
         {
           all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw;
           direct_ref_idx[LIST_1] = (char)l1_refX;
         }
       }
       else
       {
         all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv;
         direct_ref_idx[LIST_1] = -1;
       }
 
      // Test Level Limits if satisfied.
 
       // Test Level Limits if satisfied.
       if ((out_of_bounds_mvs(p_Vid, &all_mvs[LIST_0][l0_refX < 0? 0 : l0_refX][0][block_y][block_x])
         ||  out_of_bounds_mvs(p_Vid, &all_mvs[LIST_1][l1_refX < 0? 0 : l1_refX][0][block_y][block_x])))
       {
         direct_ref_idx[LIST_0] = -1;
         direct_ref_idx[LIST_1] = -1;
         currSlice->direct_pdir   [pic_block_y][pic_block_x]         = -1;
       }     
       else
       {
         if (l0_refX < 0 && l1_refX < 0)
         {
           direct_ref_idx[LIST_0] = direct_ref_idx[LIST_1] = 0;
           l0_refX = 0;
           l1_refX = 0;
         }
 
         if      (direct_ref_idx[LIST_1] == -1)
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 0;
         else if (direct_ref_idx[LIST_0] == -1)
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 1;
         else if (p_Vid->active_pps->weighted_bipred_idc == 1)
           test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x);
         else
           currSlice->direct_pdir[pic_block_y][pic_block_x] = 2;
       }
     }
   }
 }
相關文章
相關標籤/搜索