直接预测是B帧上一种独有的预测方式,其中直接预测又分为两种模式: 时域直接模式(temporal direct)、空域直接模式(spatial direct)。
在分析这两种模式之前,有一个前提概念需要了解:共同位置4x4子宏块分割块(co-located 4x4 sub-macroblock partitions),下面简称为co-located。
共同位置4x4子宏块分割块,故名思义,该块大小为4x4。co-located的主要功能是得到出该4x4块的运动向量以及参考帧,以供后面的直接预测做后续处理,如果当前宏块进行的是直接预测,无论时域或空域,都会用到该co-located,因此需要先求出该4x4co-located的具体位置。
1. 定位co-located所在图像
要求co-located的位置,首先需要知道co-located所在的图像colPic的位置,colPic可以确定在当前图像的第一个后向参考图像RefPicList1[ 0 ]内,但是colPic可以为帧或场,这取决于当期图像与参考图像,是以帧图像进行编码,还是以场图像进行编码,或者以互补场对(宏块级帧场自适应)方式进行编码。
第一项:field_pic_flag表示当前图像是以帧还是场方式进行编码
第二项:代表RefPicList1[0]的编码方式是帧、场、互补场对(两个场)
第三项:mb_field_decoding_flag代表当前宏块对是以帧、场方式进行编码(前提条件是当前图像是以帧方式进行编码,也只有当前图像选择了帧编码,才能选择宏块对(宏块帧场自适应)的编码方式)
第四项:
topAbsDiffPOC = Abs( DiffPicOrderCnt( firstRefPicL1Top, CurrPic ) )
bottomAbsDiffPOC = Abs( DiffPicOrderCnt( firstRefPicL1Bottom, CurrPic ) )
添加这些条件是为了在采用宏块级帧场自适编码方式时,应选择距离当前图像最近的顶场或底场作为col_Pic
第五项:col_Pic的取值
firstRefPicL1Top 和firstRefPicL1Bottom 分别为RefPicList1[ 0 ]中的顶场和底场
注:其实第二项RefPicList1[ 0 ]是一个被动选项,因为它是根据当前图像的编码方式是帧、场或宏块帧场自适应决定的,如果当前图像是场,那么RefPicList1[ 0 ]就有可能是已解码的场或者以解码帧中的一场;如果当前图像是帧(非MBAFF),那么RefPicList1[ 0 ]就是帧;如果当前宏块是帧并且为MBAFF,那么RefPicList1[ 0 ]就是一个互补场对(两个场可以组成一个帧)
2. 得到co-located在colPic内的位置
实际上,如果得到了colPic,就可以通过当前宏块的16个4x4块的绝对位置(以4x4块为单位相对于图像左上角(0,0)的绝对位置( opic_block_x,opic_block_y)),得到co-located在colPic的位置。
如果当前图像为帧,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 )
在标准中,先定位co-located所在宏块mbAddrCol,然后再定位co-located在该宏块内的地址(xcol,yM)。由于采用了不同于上述的4x4块定位方法,所以计算方式略复杂,但是得到的结果是一样的,最终会定位到同一个co-located
mbAddrCol1 = 2 * PicWidthInMbs * ( CurrMbAddr / PicWidthInMbs ) +
( CurrMbAddr % PicWidthInMbs ) + PicWidthInMbs * ( yCol / 8 )
mbAddrCol2 = 2 * CurrMbAddr + ( yCol / 8 )
mbAddrCol3 = 2 * CurrMbAddr + bottom_field_flag
mbAddrCol4 = PicWidthInMbs * ( CurrMbAddr / ( 2 * PicWidthInMbs ) ) +
( CurrMbAddr % PicWidthInMbs )
mbAddrCol5 = CurrMbAddr / 2
mbAddrCol6 = 2 * ( CurrMbAddr / 2 ) + ( ( topAbsDiffPOC < bottomAbsDiffPOC ) ? 0 : 1 )
mbAddrCol7 = 2 * ( CurrMbAddr / 2 ) + ( yCol / 8 )
(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
3.获得co-located的运动向量与参考帧
如果co-located是帧内预测方式编码,那么将无法获得运动向量与参考帧,mvCol = 0,refIdxCol = -1
如果co-located是帧间预测编码方式,并且存在前向参考帧,那么mvCol将是co-located的前向运动向量,refIdxCol是co-located所在的8x8块中的某一个4x4块的前向参考索引
如果co-located是帧间预测编码方式,并且只存在后向参考帧,那么mvCol将是co-located的后向运动向量,refIdxCol是co-located所在的8x8块中的某一个4x4块的后向参考索引
(注:至于如何从8x8块中选取该4x4块并沿用其参考索引,标准中并没有规定,具体可以看本文最后的代码是如何做的)
时域直接模式(temporal direct)
该模式是基于下图求出当前4x4块的前后向mvL0与mvL1,以及前向参考帧List0 reference的索引
已知的变量有:
未知的变量有:
求解方法:
由于这些在标准(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
1 /*! 2 ************************************************************************************* 3 * \file mv_direct.c 4 * 5 * \brief 6 * Direct Motion Vector Generation 7 * 8 * \author 9 * Main contributors (see contributors.h for copyright, address and affiliation details) 10 * - Alexis Michael Tourapis <[email protected]> 11 * 12 ************************************************************************************* 13 */ 14 15 #include "contributors.h" 16 17 #include <math.h> 18 #include <limits.h> 19 #include <time.h> 20 21 #include "global.h" 22 23 #include "image.h" 24 #include "mv_search.h" 25 #include "refbuf.h" 26 #include "memalloc.h" 27 #include "mb_access.h" 28 #include "macroblock.h" 29 #include "mc_prediction.h" 30 #include "conformance.h" 31 #include "mode_decision.h" 32 33 /*! 34 ************************************************************************ 35 * \brief 36 * Calculate Temporal Direct Mode Motion Vectors 37 ************************************************************************ 38 */ 39 void Get_Direct_MV_Temporal (Macroblock *currMB) 40 { 41 Slice *currSlice = currMB->p_Slice; 42 int block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y; 43 MotionVector *****all_mvs; 44 int mv_scale; 45 int refList; 46 int ref_idx; 47 VideoParameters *p_Vid = currMB->p_Vid; 48 int list_offset = currMB->list_offset;//如果当前currSlice->mb_aff_frame_flag 且 currMB->mb_field ,list_offset>0 49 50 StorablePicture **list1 = currSlice->listX[LIST_1 + list_offset]; 51 52 PicMotionParams colocated; 53 54 //temporal direct mode copy from decoder 55 for (block_y = 0; block_y < 4; block_y++) 56 { 57 pic_block_y = currMB->block_y + block_y; 58 opic_block_y = (currMB->opix_y >> 2) + block_y; 59 60 for (block_x = 0; block_x < 4; block_x++) 61 { 62 pic_block_x = currMB->block_x + block_x; 63 opic_block_x = (currMB->pix_x>>2) + block_x; 64 65 all_mvs = currSlice->all_mv; 66 if (p_Vid->active_sps->direct_8x8_inference_flag) 67 { 68 if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444) 69 colocated = list1[0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(opic_block_y)][RSD(opic_block_x)]; 70 else 71 colocated = list1[0]->mv_info[RSD(opic_block_y)][RSD(opic_block_x)]; 72 if(currSlice->mb_aff_frame_flag && currMB->mb_field && currSlice->listX[LIST_1][0]->coded_frame) 73 {//mbaff场宏块 74 int iPosBlkY; 75 if(currSlice->listX[LIST_1][0]->motion.mb_field[currMB->mbAddrX] ) 76 //当前宏块是mbaff且为场编码,参考帧宏块为场编码,不过因为此处计算ref_pic用的是frame,即一个场宏块对应两个帧宏块 77 //场宏块>>2后*8,可以对比下面帧宏块>>3后再*8 78 //>>2代表一个场宏块, 79 //*8代表宏块对(两个帧宏块), 80 //*4代表选择对应宏块(顶宏块或者底宏块其中之一(field重建回frame时,对于宏块的mv_info,是以宏块对方式组建的?)), 81 //&3代表4x4子块 82 //另外由于每一个8x8块对应一个参考帧所以最后也有RSD(opic_block_x) 83 iPosBlkY = (opic_block_y>>2)*8+4*(currMB->mbAddrX&1)+(opic_block_y&0x03); 84 else 85 //因为当前是场(mb_field)?而下面参考帧采用的是帧,则代表field->frame,所以*2 86 iPosBlkY = RSD(opic_block_y)*2; 87 88 //由于标准规定(8.4.1.2.2最后一段)在colocated中应该在其所在的8x8分割块中选取参考帧,所以需要进行以下步骤 89 if(colocated.ref_idx[LIST_0]>=0)//ref_idx>=0说明有前/后向参考帧,但是下面还需要根据当前宏块与colpic进行精确定位(即在8x8分割块中选取某块的参考帧) 90 colocated.ref_pic[LIST_0] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_0]; 91 if(colocated.ref_idx[LIST_1]>=0) 92 colocated.ref_pic[LIST_1] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_1]; 93 } 94 } 95 else 96 { 97 if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444) 98 colocated = list1[0]->JVmv_info[currMB->p_Slice->colour_plane_id][opic_block_y][opic_block_x]; 99 else 100 colocated = list1[0]->mv_info[opic_block_y][opic_block_x]; 101 } 102 if(currSlice->mb_aff_frame_flag) 103 { 104 if(!currMB->mb_field && ((currSlice->listX[LIST_1][0]->coded_frame && currSlice->listX[LIST_1][0]->motion.mb_field[currMB->mbAddrX]) || 105 (!currSlice->listX[LIST_1][0]->coded_frame))) 106 {//mbaff帧宏块 107 if (iabs(p_Vid->enc_picture->poc - currSlice->listX[LIST_1+4][0]->poc)> iabs(p_Vid->enc_picture->poc -currSlice->listX[LIST_1+2][0]->poc) ) 108 { 109 if ( p_Vid->active_sps->direct_8x8_inference_flag) 110 { 111 if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444) 112 colocated = currSlice->listX[LIST_1+2][0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(opic_block_y)>>1][RSD(opic_block_x)]; 113 else 114 colocated = currSlice->listX[LIST_1+2][0]->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)]; 115 } 116 else 117 { 118 if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444) 119 colocated = currSlice->listX[LIST_1+2][0]->JVmv_info[currMB->p_Slice->colour_plane_id][(opic_block_y)>>1][(opic_block_x)]; 120 else 121 colocated = currSlice->listX[LIST_1+2][0]->mv_info[(opic_block_y)>>1][opic_block_x]; 122 } 123 if(currSlice->listX[LIST_1][0]->coded_frame) 124 {//帧宏块,所以下面>>3后再*8,可以对比上面场宏块>>2后再*8 125 int iPosBlkY = (RSD(opic_block_y)>>3)*8 + ((RSD(opic_block_y)>>1) & 0x03); 126 if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0]) 127 colocated.ref_pic[LIST_0] = currSlice->listX[LIST_1+2][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_0]; 128 if(colocated.ref_idx[LIST_1] >=0) // && !colocated.ref_pic[LIST_1]) 129 colocated.ref_pic[LIST_1] = currSlice->listX[LIST_1+2][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_1]; 130 } 131 } 132 else 133 { 134 if (p_Vid->active_sps->direct_8x8_inference_flag ) 135 { 136 if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444) 137 colocated = currSlice->listX[LIST_1+4][0]->JVmv_info[currMB->p_Slice->colour_plane_id][RSD(opic_block_y)>>1][RSD(opic_block_x)]; 138 else 139 colocated = currSlice->listX[LIST_1+4][0]->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)]; 140 141 } 142 else 143 { 144 if(currMB->p_Inp->separate_colour_plane_flag && currMB->p_Vid->yuv_format==YUV444) 145 colocated = currSlice->listX[LIST_1+4][0]->JVmv_info[currMB->p_Slice->colour_plane_id][(opic_block_y)>>1][opic_block_x]; 146 else 147 colocated = currSlice->listX[LIST_1+4][0]->mv_info[(opic_block_y)>>1][opic_block_x]; 148 } 149 if(currSlice->listX[LIST_1][0]->coded_frame) 150 { 151 int iPosBlkY = (RSD(opic_block_y)>>3)*8 + ((RSD(opic_block_y)>>1) & 0x03)+4; 152 if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0]) 153 colocated.ref_pic[LIST_0] = currSlice->listX[LIST_1+4][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_0]; 154 if(colocated.ref_idx[LIST_1] >=0)// && !colocated.ref_pic[LIST_1]) 155 colocated.ref_pic[LIST_1] = currSlice->listX[LIST_1+4][0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_1]; 156 } 157 } 158 } 159 } 160 else if(!p_Vid->active_sps->frame_mbs_only_flag && !currSlice->structure && !currSlice->listX[LIST_1][0]->coded_frame) 161 {//图像级帧场自适应帧图像编码(即list1[0]有可能为场编码) 162 if (iabs(p_Vid->enc_picture->poc - list1[0]->bottom_field->poc)> iabs(p_Vid->enc_picture->poc -list1[0]->top_field->poc) ) 163 { 164 colocated = p_Vid->active_sps->direct_8x8_inference_flag ? 165 list1[0]->top_field->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)] : list1[0]->top_field->mv_info[(opic_block_y)>>1][opic_block_x]; 166 } 167 else 168 { 169 colocated = p_Vid->active_sps->direct_8x8_inference_flag ? 170 list1[0]->bottom_field->mv_info[RSD(opic_block_y)>>1][RSD(opic_block_x)] : list1[0]->bottom_field->mv_info[(opic_block_y)>>1][opic_block_x]; 171 } 172 } 173 else if(!p_Vid->active_sps->frame_mbs_only_flag && currSlice->structure && list1[0]->coded_frame) 174 {//场图像编码 175 int iPosBlkY; 176 int currentmb = 2*(list1[0]->size_x>>4) * (opic_block_y >> 2)+ (opic_block_x>>2)*2 + ((opic_block_y>>1) & 0x01); 177 if(currSlice->structure!=list1[0]->structure) 178 { 179 if (currSlice->structure == TOP_FIELD) 180 { 181 colocated = p_Vid->active_sps->direct_8x8_inference_flag ? 182 list1[0]->frame->top_field->mv_info[RSD(opic_block_y)][RSD(opic_block_x)] : list1[0]->frame->top_field->mv_info[opic_block_y][opic_block_x]; 183 } 184 else 185 { 186 colocated = p_Vid->active_sps->direct_8x8_inference_flag ? 187 list1[0]->frame->bottom_field->mv_info[RSD(opic_block_y)][RSD(opic_block_x)] : list1[0]->frame->bottom_field->mv_info[opic_block_y][opic_block_x]; 188 } 189 } 190 191 if(!currSlice->listX[LIST_1][0]->frame->mb_aff_frame_flag || !list1[0]->frame->motion.mb_field[currentmb]) 192 iPosBlkY = 2*(RSD(opic_block_y)); 193 else 194 iPosBlkY = (RSD(opic_block_y)>>2)*8 + (RSD(opic_block_y) & 0x03)+4*(currSlice->structure == BOTTOM_FIELD); 195 if(colocated.ref_idx[LIST_0] >=0) // && !colocated.ref_pic[LIST_0]) 196 colocated.ref_pic[LIST_0] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_0]; 197 if(colocated.ref_idx[LIST_1] >=0)// && !colocated.ref_pic[LIST_1]) 198 colocated.ref_pic[LIST_1] = list1[0]->frame->mv_info[iPosBlkY][RSD(opic_block_x)].ref_pic[LIST_1]; 199 } 200 //最后剩下的是全序列采用帧图像编码(frame_mbs_only_flag = 1),这样的话colocated.ref_pic肯定是存在的,并且不用进行帧场转换,也就是采用原来的就可以,因此不用重新赋值 201 //colocated在开头判断direct_8x8_inference_flag的两个分支处即可获得 202 203 refList = ((colocated.ref_idx[LIST_0] == -1 || (p_Vid->view_id && colocated.ref_idx[LIST_0]==list1[0]->ref_pic_na[0]))? LIST_1 : LIST_0); 204 ref_idx = colocated.ref_idx[refList]; 205 206 // next P is intra mode 207 if (ref_idx == -1 || (p_Vid->view_id && ref_idx==list1[0]->ref_pic_na[refList])) 208 { 209 all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv; 210 all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv; 211 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = 0; 212 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = 0; 213 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2; 214 } 215 // next P is skip or inter mode 216 else 217 { 218 int mapped_idx=INVALIDINDEX; 219 int iref; 220 if (colocated.ref_pic[refList] == NULL) 221 { 222 printf("invalid index found\n"); 223 } 224 else 225 { //得到前向参考帧ref0,即下面的mapped_idx 226 //Let refIdxL0Frm be the lowest valued reference index in the current reference picture list RefPicList0 that 227 //references the frame or complementary field pair that contains the field refPicCol 228 if( (currSlice->mb_aff_frame_flag && ( (currMB->mb_field && colocated.ref_pic[refList]->structure==FRAME) || //currSlice :mbaff & mb_field, ref_pic :frame 229 (!currMB->mb_field && colocated.ref_pic[refList]->structure!=FRAME))) || //currSlice :mb_frame , ref_pic :field 230 (!currSlice->mb_aff_frame_flag && ((currSlice->structure==FRAME && colocated.ref_pic[refList]->structure!=FRAME)|| //currSlice :frame only , ref_pic :field 231 (currSlice->structure!=FRAME && colocated.ref_pic[refList]->structure==FRAME))) ) //currSlice :field , ref_pic :frame 232 {//该判断条件表示currSlice与ref_pic用不同的帧场编码方式 233 //! Frame with field co-located 234 for (iref = 0; iref < imin(currSlice->num_ref_idx_active[LIST_0], currSlice->listXsize[LIST_0 + list_offset]); iref++) 235 { 236 if (currSlice->listX[LIST_0 + list_offset][iref]->top_field == colocated.ref_pic[refList] || 237 currSlice->listX[LIST_0 + list_offset][iref]->bottom_field == colocated.ref_pic[refList] || 238 currSlice->listX[LIST_0 + list_offset][iref]->frame == colocated.ref_pic[refList] ) 239 { 240 if ((p_Vid->field_picture==1) && (currSlice->listX[LIST_0 + list_offset][iref]->structure != currSlice->structure)) 241 {//currSlice :field , ref_pic :frame 会进来这里? 242 mapped_idx=INVALIDINDEX; 243 } 244 else 245 { 246 mapped_idx = iref; 247 break; 248 } 249 } 250 else //! invalid index. Default to zero even though this case should not happen 251 mapped_idx=INVALIDINDEX; 252 } 253 } 254 else 255 {//currSlice 与 ref_pic 采用相同帧场编码方式 256 for (iref = 0; iref < imin(currSlice->num_ref_idx_active[LIST_0], currSlice->listXsize[LIST_0 + list_offset]);iref++) 257 { 258 if(currSlice->listX[LIST_0 + list_offset][iref] == colocated.ref_pic[refList]) 259 { 260 mapped_idx = iref; 261 break; 262 } 263 else //! invalid index. Default to zero even though this case should not happen 264 { 265 mapped_idx=INVALIDINDEX; 266 } 267 } 268 } 269 } 270 if (mapped_idx != INVALIDINDEX) 271 { 272 MotionVector mv = colocated.mv[refList]; 273 mv_scale = currSlice->mvscale[LIST_0 + list_offset][mapped_idx]; 274 275 if((currSlice->mb_aff_frame_flag && !currMB->mb_field && colocated.ref_pic[refList]->structure!=FRAME) || 276 (!currSlice->mb_aff_frame_flag && currSlice->structure==FRAME && colocated.ref_pic[refList]->structure!=FRAME)) 277 mv.mv_y *= 2; 278 else if((currSlice->mb_aff_frame_flag && currMB->mb_field && colocated.ref_pic[refList]->structure==FRAME) || 279 (!currSlice->mb_aff_frame_flag && currSlice->structure!=FRAME && colocated.ref_pic[refList]->structure==FRAME)) 280 mv.mv_y /= 2; 281 282 //mvL0,mvL1 283 if (mv_scale==9999) 284 { 285 // forward 286 all_mvs[LIST_0][0][0][block_y][block_x] = mv; 287 // backward 288 all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv; 289 } 290 else 291 { 292 //mv_scale = DistScaleFactor (in function compute_colocated) 293 // forward 294 all_mvs[LIST_0][mapped_idx][0][block_y][block_x].mv_x = (short) ((mv_scale * mv.mv_x + 128) >> 8); 295 all_mvs[LIST_0][mapped_idx][0][block_y][block_x].mv_y = (short) ((mv_scale * mv.mv_y + 128) >> 8); 296 // backward 297 all_mvs[LIST_1][ 0][0][block_y][block_x].mv_x = (short) (((mv_scale - 256) * mv.mv_x + 128) >> 8); 298 all_mvs[LIST_1][ 0][0][block_y][block_x].mv_y = (short) (((mv_scale - 256) * mv.mv_y + 128) >> 8); 299 300 } 301 //refIdx0,refIdx1 302 // Test Level Limits if satisfied. 303 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[LIST_1][0][0][block_y][block_x])) 304 { 305 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1; 306 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1; 307 currSlice->direct_pdir[pic_block_y][pic_block_x] = -1; 308 } 309 else 310 { 311 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = (char) mapped_idx; 312 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = 0; 313 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2; 314 } 315 } 316 else 317 { 318 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1; 319 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1; 320 currSlice->direct_pdir[pic_block_y][pic_block_x] = -1; 321 } 322 } 323 324 if (p_Vid->active_pps->weighted_bipred_idc == 1 && currSlice->direct_pdir[pic_block_y][pic_block_x] == 2) 325 { 326 int weight_sum, i; 327 short l0_refX = currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0]; 328 short l1_refX = currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1]; 329 for (i=0;i< (p_Vid->active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++) 330 { 331 weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i]; 332 if (weight_sum < -128 || weight_sum > 127) 333 { 334 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_0] = -1; 335 currSlice->direct_ref_idx[pic_block_y][pic_block_x][LIST_1] = -1; 336 currSlice->direct_pdir [pic_block_y][pic_block_x] = -1; 337 break; 338 } 339 } 340 } 341 } 342 } 343 } 344 345 static inline void set_direct_references(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info) 346 { 347 if (mb->available) 348 { 349 char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx; 350 *l0_rFrame = ref_idx[LIST_0]; 351 *l1_rFrame = ref_idx[LIST_1]; 352 } 353 else 354 { 355 *l0_rFrame = -1; 356 *l1_rFrame = -1; 357 } 358 } 359 360 static void set_direct_references_mb_field(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info, Macroblock *mb_data) 361 { 362 if (mb->available) 363 { 364 char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx; 365 if (mb_data[mb->mb_addr].mb_field) 366 { 367 *l0_rFrame = ref_idx[LIST_0]; 368 *l1_rFrame = ref_idx[LIST_1]; 369 } 370 else 371 { 372 *l0_rFrame = (ref_idx[LIST_0] < 0) ? ref_idx[LIST_0] : ref_idx[LIST_0] * 2; 373 *l1_rFrame = (ref_idx[LIST_1] < 0) ? ref_idx[LIST_1] : ref_idx[LIST_1] * 2; 374 } 375 } 376 else 377 { 378 *l0_rFrame = -1; 379 *l1_rFrame = -1; 380 } 381 } 382 383 static void set_direct_references_mb_frame(const PixelPos *mb, char *l0_rFrame, char *l1_rFrame, PicMotionParams **mv_info, Macroblock *mb_data) 384 { 385 if (mb->available) 386 { 387 char *ref_idx = mv_info[mb->pos_y][mb->pos_x].ref_idx; 388 if (mb_data[mb->mb_addr].mb_field) 389 { 390 *l0_rFrame = (ref_idx[LIST_0] >> 1); 391 *l1_rFrame = (ref_idx[LIST_1] >> 1); 392 } 393 else 394 { 395 *l0_rFrame = ref_idx[LIST_0]; 396 *l1_rFrame = ref_idx[LIST_1]; 397 } 398 } 399 else 400 { 401 *l0_rFrame = -1; 402 *l1_rFrame = -1; 403 } 404 } 405 406 static void test_valid_direct(Slice *currSlice, seq_parameter_set_rbsp_t *active_sps, char *direct_ref_idx, short l0_refX, short l1_refX, int pic_block_y, int pic_block_x) 407 { 408 int weight_sum, i; 409 Boolean invalid_wp = FALSE; 410 for (i=0;i< (active_sps->chroma_format_idc == YUV400 ? 1 : 3); i++) 411 { 412 weight_sum = currSlice->wbp_weight[0][l0_refX][l1_refX][i] + currSlice->wbp_weight[1][l0_refX][l1_refX][i]; 413 if (weight_sum < -128 || weight_sum > 127) 414 { 415 invalid_wp = TRUE; 416 break; 417 } 418 } 419 if (invalid_wp == FALSE) 420 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2; 421 else 422 { 423 direct_ref_idx[LIST_0] = -1; 424 direct_ref_idx[LIST_1] = -1; 425 currSlice->direct_pdir[pic_block_y][pic_block_x] = -1; 426 } 427 } 428 429 /*! 430 ************************************************************************************* 431 * \brief 432 * Temporary function for colocated info when direct_inference is enabled. 433 * 434 ************************************************************************************* 435 */ 436 int get_colocated_info(Macroblock *currMB, StorablePicture *list1, int i, int j) 437 { 438 if (list1->is_long_term) 439 return 1; 440 else 441 { 442 Slice *currSlice = currMB->p_Slice; 443 VideoParameters *p_Vid = currMB->p_Vid; 444 if( (currSlice->mb_aff_frame_flag) || 445 (!p_Vid->active_sps->frame_mbs_only_flag && ((!currSlice->structure && !list1->coded_frame) || (currSlice->structure!=list1->structure && list1->coded_frame)))) 446 { 447 int jj = RSD(j); 448 int ii = RSD(i); 449 int jdiv = (jj>>1); 450 int moving; 451 PicMotionParams *fs = &list1->mv_info[jj][ii]; 452 453 if(currSlice->structure && currSlice->structure!=list1->structure && list1->coded_frame) 454 { 455 if(currSlice->structure == TOP_FIELD) 456 fs = list1->top_field->mv_info[jj] + ii; 457 else 458 fs = list1->bottom_field->mv_info[jj] + ii; 459 } 460 else 461 { 462 if( (currSlice->mb_aff_frame_flag && ((!currMB->mb_field && list1->motion.mb_field[currMB->mbAddrX]) || 463 (!currMB->mb_field && !list1->coded_frame))) 464 || (!currSlice->mb_aff_frame_flag)) 465 { 466 if (iabs(p_Vid->enc_picture->poc - list1->bottom_field->poc)> iabs(p_Vid->enc_picture->poc -list1->top_field->poc) ) 467 { 468 fs = list1->top_field->mv_info[jdiv] + ii; 469 } 470 else 471 { 472 fs = list1->bottom_field->mv_info[jdiv] + ii; 473 } 474 } 475 } 476 moving = !((((fs->ref_idx[LIST_0] == 0) 477 && (iabs(fs->mv[LIST_0].mv_x)>>1 == 0) 478 && (iabs(fs->mv[LIST_0].mv_y)>>1 == 0))) 479 || ((fs->ref_idx[LIST_0] == -1) 480 && (fs->ref_idx[LIST_1] == 0) 481 && (iabs(fs->mv[LIST_1].mv_x)>>1 == 0) 482 && (iabs(fs->mv[LIST_1].mv_y)>>1 == 0))); 483 return moving; 484 } 485 else 486 { 487 PicMotionParams *fs = &list1->mv_info[RSD(j)][RSD(i)]; 488 int moving; 489 if(currMB->p_Vid->yuv_format == YUV444 && !currSlice->P444_joined) 490 fs = &list1->JVmv_info[(int)(p_Vid->colour_plane_id)][RSD(j)][RSD(i)]; 491 moving= !((((fs->ref_idx[LIST_0] == 0) 492 && (iabs(fs->mv[LIST_0].mv_x)>>1 == 0) 493 && (iabs(fs->mv[LIST_0].mv_y)>>1 == 0))) 494 || ((fs->ref_idx[LIST_0] == -1) 495 && (fs->ref_idx[LIST_1] == 0) 496 && (iabs(fs->mv[LIST_1].mv_x)>>1 == 0) 497 && (iabs(fs->mv[LIST_1].mv_y)>>1 == 0))); 498 499 return moving; 500 } 501 } 502 } 503 504 /*! 505 ************************************************************************************* 506 * \brief 507 * Colocated info <= direct_inference is disabled. 508 ************************************************************************************* 509 */ 510 int get_colocated_info_4x4(Macroblock *currMB, StorablePicture *list1, int i, int j) 511 { 512 if (list1->is_long_term) 513 return 1; 514 else 515 { 516 PicMotionParams *fs = &list1->mv_info[j][i]; 517 518 int moving = !((((fs->ref_idx[LIST_0] == 0) 519 && (iabs(fs->mv[LIST_0].mv_x)>>1 == 0) 520 && (iabs(fs->mv[LIST_0].mv_y)>>1 == 0))) 521 || ((fs->ref_idx[LIST_0] == -1) 522 && (fs->ref_idx[LIST_1] == 0) 523 && (iabs(fs->mv[LIST_1].mv_x)>>1 == 0) 524 && (iabs(fs->mv[LIST_1].mv_y)>>1 == 0))); 525 526 return moving; 527 } 528 } 529 530 /*! 531 ************************************************************************ 532 * \brief 533 * Calculate Spatial Direct Mode Motion Vectors 534 ************************************************************************ 535 */ 536 void Get_Direct_MV_Spatial_Normal (Macroblock *currMB) 537 { 538 Slice *currSlice = currMB->p_Slice; 539 VideoParameters *p_Vid = currMB->p_Vid; 540 PicMotionParams **mv_info = p_Vid->enc_picture->mv_info; 541 char l0_refA, l0_refB, l0_refC; 542 char l1_refA, l1_refB, l1_refC; 543 char l0_refX,l1_refX; 544 MotionVector pmvfw = zero_mv, pmvbw = zero_mv; 545 546 int block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y; 547 MotionVector *****all_mvs; 548 char *direct_ref_idx; 549 StorablePicture **list1 = currSlice->listX[LIST_1]; 550 551 PixelPos mb[4]; 552 get_neighbors(currMB, mb, 0, 0, 16); 553 554 set_direct_references(&mb[0], &l0_refA, &l1_refA, mv_info); 555 set_direct_references(&mb[1], &l0_refB, &l1_refB, mv_info); 556 set_direct_references(&mb[2], &l0_refC, &l1_refC, mv_info); 557 558 l0_refX = (char) imin(imin((unsigned char) l0_refA, (unsigned char) l0_refB), (unsigned char) l0_refC); 559 l1_refX = (char) imin(imin((unsigned char) l1_refA, (unsigned char) l1_refB), (unsigned char) l1_refC); 560 561 if (l0_refX >= 0) 562 currMB->GetMVPredictor (currMB, mb, &pmvfw, l0_refX, mv_info, LIST_0, 0, 0, 16, 16); 563 564 if (l1_refX >= 0) 565 currMB->GetMVPredictor (currMB, mb, &pmvbw, l1_refX, mv_info, LIST_1, 0, 0, 16, 16); 566 567 if (l0_refX == -1 && l1_refX == -1) 568 { 569 for (block_y=0; block_y<4; block_y++) 570 { 571 pic_block_y = currMB->block_y + block_y; 572 for (block_x=0; block_x<4; block_x++) 573 { 574 pic_block_x = currMB->block_x + block_x; 575 direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x]; 576 577 currSlice->all_mv[LIST_0][0][0][block_y][block_x] = zero_mv; 578 currSlice->all_mv[LIST_1][0][0][block_y][block_x] = zero_mv; 579 580 direct_ref_idx[LIST_0] = direct_ref_idx[LIST_1] = 0; 581 582 if (p_Vid->active_pps->weighted_bipred_idc == 1) 583 test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, 0, 0, pic_block_y, pic_block_x); 584 else 585 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2; 586 } 587 } 588 } 589 else if (l0_refX == 0 || l1_refX == 0) 590 { 591 int (*get_colocated)(Macroblock *currMB, StorablePicture *list1, int i, int j) = 592 p_Vid->active_sps->direct_8x8_inference_flag ? get_colocated_info : get_colocated_info_4x4; 593 594 int is_moving_block; 595 for (block_y = 0; block_y < 4; block_y++) 596 { 597 pic_block_y = currMB->block_y + block_y; 598 opic_block_y = (currMB->opix_y >> 2) + block_y; 599 600 for (block_x=0; block_x<4; block_x++) 601 { 602 pic_block_x = currMB->block_x + block_x; 603 direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x]; 604 opic_block_x = (currMB->pix_x >> 2) + block_x; 605 606 all_mvs = currSlice->all_mv; 607 is_moving_block = (get_colocated(currMB, list1[0], opic_block_x, opic_block_y) == 0); 608 609 if (l0_refX < 0) 610 { 611 all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv; 612 direct_ref_idx[LIST_0] = -1; 613 } 614 else if ((l0_refX == 0) && is_moving_block) 615 { 616 all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv; 617 direct_ref_idx[LIST_0] = 0; 618 } 619 else 620 { 621 all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw; 622 direct_ref_idx[LIST_0] = (char)l0_refX; 623 } 624 625 if (l1_refX < 0) 626 { 627 all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv; 628 direct_ref_idx[LIST_1] = -1; 629 } 630 else if((l1_refX == 0) && is_moving_block) 631 { 632 all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv; 633 direct_ref_idx[LIST_1] = 0; 634 } 635 else 636 { 637 all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw; 638 direct_ref_idx[LIST_1] = (char)l1_refX; 639 } 640 641 if (direct_ref_idx[LIST_1] == -1) 642 currSlice->direct_pdir[pic_block_y][pic_block_x] = 0; 643 else if (direct_ref_idx[LIST_0] == -1) 644 currSlice->direct_pdir[pic_block_y][pic_block_x] = 1; 645 else if (p_Vid->active_pps->weighted_bipred_idc == 1) 646 test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x); 647 else 648 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2; 649 } 650 } 651 } 652 else 653 { 654 for (block_y=0; block_y<4; block_y++) 655 { 656 pic_block_y = currMB->block_y + block_y; 657 658 for (block_x=0; block_x<4; block_x++) 659 { 660 pic_block_x = currMB->block_x + block_x; 661 direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x]; 662 663 all_mvs = currSlice->all_mv; 664 665 if (l0_refX > 0) 666 { 667 all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw; 668 direct_ref_idx[LIST_0]= (char)l0_refX; 669 } 670 else 671 { 672 all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv; 673 direct_ref_idx[LIST_0]=-1; 674 } 675 676 if (l1_refX > 0) 677 { 678 all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw; 679 direct_ref_idx[LIST_1] = (char)l1_refX; 680 } 681 else 682 { 683 all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv; 684 direct_ref_idx[LIST_1] = -1; 685 } 686 687 if (direct_ref_idx[LIST_1] == -1) 688 currSlice->direct_pdir[pic_block_y][pic_block_x] = 0; 689 else if (direct_ref_idx[LIST_0] == -1) 690 currSlice->direct_pdir[pic_block_y][pic_block_x] = 1; 691 else if (p_Vid->active_pps->weighted_bipred_idc == 1) 692 test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x); 693 else 694 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2; 695 } 696 } 697 } 698 } 699 700 701 /*! 702 ************************************************************************ 703 * \brief 704 * Calculate Spatial Direct Mode Motion Vectors 705 ************************************************************************ 706 */ 707 void Get_Direct_MV_Spatial_MBAFF (Macroblock *currMB) 708 { 709 char l0_refA, l0_refB, l0_refC; 710 char l1_refA, l1_refB, l1_refC; 711 char l0_refX,l1_refX; 712 MotionVector pmvfw = zero_mv, pmvbw = zero_mv; 713 714 int block_x, block_y, pic_block_x, pic_block_y, opic_block_x, opic_block_y; 715 MotionVector *****all_mvs; 716 char *direct_ref_idx; 717 int is_moving_block; 718 Slice *currSlice = currMB->p_Slice; 719 VideoParameters *p_Vid = currMB->p_Vid; 720 PicMotionParams **mv_info = p_Vid->enc_picture->mv_info; 721 StorablePicture **list1 = currSlice->listX[LIST_1 + currMB->list_offset]; 722 723 int (*get_colocated)(Macroblock *currMB, StorablePicture *list1, int i, int j) = 724 p_Vid->active_sps->direct_8x8_inference_flag ? get_colocated_info : get_colocated_info_4x4; 725 726 PixelPos mb[4]; 727 get_neighbors(currMB, mb, 0, 0, 16); 728 729 730 if (currMB->mb_field) 731 { 732 set_direct_references_mb_field(&mb[0], &l0_refA, &l1_refA, mv_info, p_Vid->mb_data); 733 set_direct_references_mb_field(&mb[1], &l0_refB, &l1_refB, mv_info, p_Vid->mb_data); 734 set_direct_references_mb_field(&mb[2], &l0_refC, &l1_refC, mv_info, p_Vid->mb_data); 735 } 736 else 737 { 738 set_direct_references_mb_frame(&mb[0], &l0_refA, &l1_refA, mv_info, p_Vid->mb_data); 739 set_direct_references_mb_frame(&mb[1], &l0_refB, &l1_refB, mv_info, p_Vid->mb_data); 740 set_direct_references_mb_frame(&mb[2], &l0_refC, &l1_refC, mv_info, p_Vid->mb_data); 741 } 742 743 l0_refX = (char) imin(imin((unsigned char) l0_refA, (unsigned char) l0_refB), (unsigned char) l0_refC); 744 l1_refX = (char) imin(imin((unsigned char) l1_refA, (unsigned char) l1_refB), (unsigned char) l1_refC); 745 746 if (l0_refX >=0) 747 currMB->GetMVPredictor (currMB, mb, &pmvfw, l0_refX, mv_info, LIST_0, 0, 0, 16, 16); 748 749 if (l1_refX >=0) 750 currMB->GetMVPredictor (currMB, mb, &pmvbw, l1_refX, mv_info, LIST_1, 0, 0, 16, 16); 751 752 for (block_y=0; block_y<4; block_y++) 753 { 754 pic_block_y = currMB->block_y + block_y; 755 opic_block_y = (currMB->opix_y >> 2) + block_y; 756 757 for (block_x=0; block_x<4; block_x++) 758 { 759 pic_block_x = currMB->block_x + block_x; 760 direct_ref_idx = currSlice->direct_ref_idx[pic_block_y][pic_block_x]; 761 opic_block_x = (currMB->pix_x >> 2) + block_x; 762 is_moving_block = (get_colocated(currMB, list1[0], opic_block_x, opic_block_y) == 0); 763 764 all_mvs = currSlice->all_mv; 765 766 if (l0_refX >=0) 767 { 768 if (!l0_refX && is_moving_block) 769 { 770 all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv; 771 direct_ref_idx[LIST_0] = 0; 772 } 773 else 774 { 775 all_mvs[LIST_0][(short) l0_refX][0][block_y][block_x] = pmvfw; 776 direct_ref_idx[LIST_0] = (char)l0_refX; 777 } 778 } 779 else 780 { 781 all_mvs[LIST_0][0][0][block_y][block_x] = zero_mv; 782 direct_ref_idx[LIST_0] = -1; 783 } 784 785 if (l1_refX >=0) 786 { 787 if(l1_refX==0 && is_moving_block) 788 { 789 all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv; 790 direct_ref_idx[LIST_1] = (char)l1_refX; 791 } 792 else 793 { 794 all_mvs[LIST_1][(short) l1_refX][0][block_y][block_x] = pmvbw; 795 direct_ref_idx[LIST_1] = (char)l1_refX; 796 } 797 } 798 else 799 { 800 all_mvs[LIST_1][0][0][block_y][block_x] = zero_mv; 801 direct_ref_idx[LIST_1] = -1; 802 } 803 804 // Test Level Limits if satisfied. 805 806 // Test Level Limits if satisfied. 807 if ((out_of_bounds_mvs(p_Vid, &all_mvs[LIST_0][l0_refX < 0? 0 : l0_refX][0][block_y][block_x]) 808 || out_of_bounds_mvs(p_Vid, &all_mvs[LIST_1][l1_refX < 0? 0 : l1_refX][0][block_y][block_x]))) 809 { 810 direct_ref_idx[LIST_0] = -1; 811 direct_ref_idx[LIST_1] = -1; 812 currSlice->direct_pdir [pic_block_y][pic_block_x] = -1; 813 } 814 else 815 { 816 if (l0_refX < 0 && l1_refX < 0) 817 { 818 direct_ref_idx[LIST_0] = direct_ref_idx[LIST_1] = 0; 819 l0_refX = 0; 820 l1_refX = 0; 821 } 822 823 if (direct_ref_idx[LIST_1] == -1) 824 currSlice->direct_pdir[pic_block_y][pic_block_x] = 0; 825 else if (direct_ref_idx[LIST_0] == -1) 826 currSlice->direct_pdir[pic_block_y][pic_block_x] = 1; 827 else if (p_Vid->active_pps->weighted_bipred_idc == 1) 828 test_valid_direct(currSlice, currSlice->active_sps, direct_ref_idx, l0_refX, l1_refX, pic_block_y, pic_block_x); 829 else 830 currSlice->direct_pdir[pic_block_y][pic_block_x] = 2; 831 } 832 } 833 } 834 }