转载于:http://blog.sina.com.cn/s/blog_6938cd0501011qk1.html
staticinlinevoidx264_mb_cache_mv_p8x8(x264_t*h,x264_mb_analysis_t*a,inti)
{
constintx=2*(i%2);
constinty=2*(i/2);
switch(h->mb.i_sub_partition[i])//之前应该有一个遍历i的循环
{
caseD_L0_8x8:
x264_macroblock_cache_mv_ptr(h,x,y,2,2,0,a->l0.me8x8[i].mv);
break;
caseD_L0_8x4:
x264_macroblock_cache_mv_ptr(h,x,y+0,2,1,0,a->l0.me8x4[i][0].mv);//me8x4[i][0]第一维应该是表示16*16的第几个8*8块,而第二维的[0]应该是表示是8*4的上半块,如果是[1]表示的就是下半块了。
x264_macroblock_cache_mv_ptr(h,x,y+1,2,1,0,a->l0.me8x4[i][1].mv);
break;
caseD_L0_4x8:
x264_macroblock_cache_mv_ptr(h,x+0,y,1,2,0,a->l0.me4x8[i][0].mv);
x264_macroblock_cache_mv_ptr(h,x+1,y,1,2,0,a->l0.me4x8[i][1].mv);
break;
caseD_L0_4x4:
x264_macroblock_cache_mv_ptr(h,x+0,y+0,1,1,0,a->l0.me4x4[i][0].mv);
x264_macroblock_cache_mv_ptr(h,x+1,y+0,1,1,0,a->l0.me4x4[i][1].mv);
x264_macroblock_cache_mv_ptr(h,x+0,y+1,1,1,0,a->l0.me4x4[i][2].mv);
x264_macroblock_cache_mv_ptr(h,x+1,y+1,1,1,0,a->l0.me4x4[i][3].mv);
break;
default:
x264_log(h,X264_LOG_ERROR,"internalerror\n");
break;
}
}
x264_macroblock_cache_mv_ptr(h,x+0,y+0,1,1,0,a->l0.me4x4[i][0].mv);
#definex264_macroblock_cache_mv_ptr(a,x,y,w,h,l,mv)x264_macroblock_cache_mv(a,x,y,w,h,l,*(uint32_t*)mv)//转换指针类型并取其值
staticALWAYS_INLINEvoidx264_macroblock_cache_mv(x264_t*h,intx,inty,intwidth,intheight,inti_list,uint32_tmv)
{
x264_macroblock_cache_rect4(&h->mb.cache.mv[i_list][X264_SCAN8_0+x+8*y],width,height,mv);//x,y用来对luma进行偏移
}
#defineX264_SCAN8_0(4+1*8)//SCAN8里的第一个LUMA值
#defineWORD_SIZEsizeof(void*)//sizeof(void*)==sizeof(int(*)(void))就是四字节了
staticALWAYS_INLINEvoidx264_macroblock_cache_rect4(void*dst,intwidth,intheight,uint32_tval)
{
intdy;
if(width==1||WORD_SIZE<8){
for(dy=0;dy<height;dy++)
{
((uint32_t*)dst)[8*dy+0]=val;//这里看width最多是4,都是赋同一个值(mv),所以是给一个方阵全赋一个值,因为dst是从luma开始,所以这里就是SCAN8的LUMA的那个方阵没错了
if(width>=2)((uint32_t*)dst)[8*dy+1]=val;
if(width==4)((uint32_t*)dst)[8*dy+2]=val;
if(width==4)((uint32_t*)dst)[8*dy+3]=val;
}
}
else
{
uint64_tval64=val+((uint64_t)val<<32);//uint64_t64位int(其实是长整型)
for(dy=0;dy<height;dy++)
{
((uint64_t*)dst)[4*dy+0]=val64;
if(width==4)((uint64_t*)dst)[4*dy+1]=val64;
}
}
}
voidx264_mb_load_mv_direct8x8(x264_t*h,intidx)
{//idx是4个8x8的ID,下面
constintx=2*(idx%2);
constinty=2*(idx/2);//这个处理和之后x264_macroblock_cache_intra8x8_pred里的处理结果是一样的
x264_macroblock_cache_ref(h,x,y,2,2,0,h->mb.cache.direct_ref[0][idx]);//list0
x264_macroblock_cache_ref(h,x,y,2,2,1,h->mb.cache.direct_ref[1][idx]);//list1
*(uint64_t*)h->mb.cache.mv[0][x264_scan8[idx*4]]=
*(uint64_t*)h->mb.cache.direct_mv[0][x264_scan8[idx*4]];这里代码原理类似x264_macroblock_cache_intra8x8_pred//因是三维数组,且最后一维有二个元素,故一个L是32位,一次COPY两个就是64位,注意这里之所以能肆无忌殚地扩容指针,是因为最后一维是[2]
*(uint64_t*)h->mb.cache.mv[0][x264_scan8[idx*4]+8]=
*(uint64_t*)h->mb.cache.direct_mv[0][x264_scan8[idx*4]+8];//+8换一行
*(uint64_t*)h->mb.cache.mv[1][x264_scan8[idx*4]]=
*(uint64_t*)h->mb.cache.direct_mv[1][x264_scan8[idx*4]];
*(uint64_t*)h->mb.cache.mv[1][x264_scan8[idx*4]+8]=
*(uint64_t*)h->mb.cache.direct_mv[1][x264_scan8[idx*4]+8];
}//idx=0是左上块,idx=1是右上块,一次COPY一个块,包括mv的x,y,以此类推
int8_tdirect_ref[2][48];
int16_tmv[2][X264_SCAN8_SIZE][2]
staticALWAYS_INLINEvoidx264_macroblock_cache_ref(x264_t*h,intx,inty,intwidth,intheight,inti_list,uint8_tref)
{
x264_macroblock_cache_rect1(&h->mb.cache.ref[i_list][X264_SCAN8_0+x+8*y],width,height,ref);//一次y偏移8就移动到了下一行的luma
}//从函数名看是存参考帧,这里的width和height应该是以4*4的MB为单位的,如16*8的分块,则width=4,height=2
staticALWAYS_INLINEvoidx264_macroblock_cache_rect1(void*dst,intwidth,intheight,uint8_tval)
{
if(width==4)//16x16或16x8
{
uint32_tval2=val*0x01010101;//一次四个字节,就是四个unsignedchar,也就是一个int
((uint32_t*)dst)[0]=val2;//通过改变指针类型,增大移动长度,一条语句赋值一行,然后[2]指针往下移动了32*2=64位,正是下一行(8x8=64)
if(height>=2)((uint32_t*)dst)[2]=val2;
if(height==4)((uint32_t*)dst)[4]=val2;
if(height==4)((uint32_t*)dst)[6]=val2;
}//这样一次赋完luma块,这里的luma是8x4x4
else//2//即8x16
{
uint32_tval2=val*0x0101;//一次四个字节
((uint16_t*)dst)[0]=val2;
if(height>=2)((uint16_t*)dst)[4]=val2;
if(height==4)((uint16_t*)dst)[8]=val2;
if(height==4)((uint16_t*)dst)[12]=val2;
}//只有一半,故赋半行即可
}
int8_tref[2][48];
x264_macroblock_cache_intra8x8_pred(h,2*(i&1),2*(i>>1),
a->i_predict8x8[i]);
staticALWAYS_INLINEvoidx264_macroblock_cache_intra8x8_pred(x264_t*h,intx,inty,inti_mode)
{
int8_t*cache=&h->mb.cache.intra4x4_pred_mode[X264_SCAN8_0+x+8*y];
cache[0]=cache[1]=cache[8]=cache[9]=i_mode;//x=0,y=0是LUMA方阵中的第一个8x8块,(2,0)是luma方阵第二个(右上),(0,2)是第三个(左下),(2,2)是第四个(右下),根据之前i为0,1,2,3在函数的参数列表里作了处理
}
int8_tintra4x4_pred_mode[48];