摘自百度快照 http://mawnja.blog.163.com/blog/static/21206198200874780810/
memcpy ( &h ->mb.pic.p_fdec [i][-1-FDEC_STRIDE ], &plane_fdec [-1-i_stride ], w *3/2 +1 );
这里为什么拷贝 w *3/2 +1 个数据?h->mb.pic.p_fdec [i][-1-FDEC_STRIDE ]里面应该只能拷贝1 个值。
解答: 看 memcpy () 函数,里面参数是指针。&h ->mb.pic.p_fdec [i][-1-FDEC_STRIDE ] 只是个首地址。对这毕书P212页,图8-22看(注意:图上只画了4*4的块,而这里操作的是16*16宏块) ,对于Y(U、V的类似)宏块需要上面1 行共需要25个数据,需要左边1 列共16个数据。
h->mb.pic.p_fdec [i][-1-FDEC_STRIDE ] 对应M, memcpy ( &h ->mb.pic.p_fdec [i][-1-FDEC_STRIDE ], &plane_fdec [-1-i_stride ], w *3/2 +1 ); 是取上面1 行25个数据。
for( j = 0; j < w ; j++ )
h->mb.pic.p_fdec [i][-1 +j*FDEC_STRIDE] = plane_fdec[-1 +j*i_stride]; 是取左边1 列16个数据
0(M) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
1 x x x x x x x x x x x x x x x x
2 x x x x x x x x x x x x x x x x
3 x x x x x x x x x x x x x x x x
4 x x x x x x x x x x x x x x x x
5 x x x x x x x x x x x x x x x x
6 x x x x x x x x x x x x x x x x
7 x x x x x x x x x x x x x x x x
8 x x x x x x x x x x x x x x x x
9 x x x x x x x x x x x x x x x x
10 x x x x x x x x x x x x x x x x
11 x x x x x x x x x x x x x x x x
12 x x x x x x x x x x x x x x x x
13 x x x x x x x x x x x x x x x x
14 x x x x x x x x x x x x x x x x
15 x x x x x x x x x x x x x x x x
16 x x x x x x x x x x x x x x x x
另一个问题
unsigned int i_neighbour8[4]; /* neighbours of each 8x8 or 4x4 block that are available */
unsigned int i_neighbour4[16]; /* at the time the block is coded */
......................................................................................
h->mb.i_neighbour4[0] =
h->mb.i_neighbour8[0] = (h->mb.i_neighbour & (MB_TOP|MB_LEFT|MB_TOPLEFT))
| ((h->mb.i_neighbour & MB_TOP) ? MB_TOPRIGHT : 0);
h->mb.i_neighbour4[4] =
h->mb.i_neighbour4[1 ] = MB_LEFT
| ((h->mb.i_neighbour & MB_TOP) ? (MB_TOP|MB_TOPLEFT|MB_TOPRIGHT) : 0);
h->mb.i_neighbour4[2] =
h->mb.i_neighbour4[8] =
h->mb.i_neighbour4[10] =
h->mb.i_neighbour8[2] = MB_TOP|MB_TOPRIGHT
| ((h->mb.i_neighbour & MB_LEFT) ? (MB_LEFT|MB_TOPLEFT) : 0);
h->mb.i_neighbour4[3] =
h->mb.i_neighbour4[7] =
h->mb.i_neighbour4[11] =
h->mb.i_neighbour4[13] =
h->mb.i_neighbour4[15] =
h->mb.i_neighbour8[3] = MB_LEFT|MB_TOP|MB_TOPLEFT;
h->mb.i_neighbour4[5] =
h->mb.i_neighbour8[1 ] = MB_LEFT | (h->mb.i_neighbour & MB_TOPRIGHT)
| ((h->mb.i_neighbour & MB_TOP) ? MB_TOP|MB_TOPLEFT : 0);
h->mb.i_neighbour4[6] =
h->mb.i_neighbour4[9] =
h->mb.i_neighbour4[12] =
h->mb.i_neighbour4[14] = MB_LEFT|MB_TOP|MB_TOPLEFT|MB_TOPRIGHT;
从注释看h->mb.i_neighbour8[]表示可参考的相邻块状态(这个懂,不管它),h->mb.i_neighbour4[]表示当前编码的块,那么我想h->mb.i_neighbour4[0]到h->mb.i_neighbour4[15]值应该是一样的 ,都表示该块有没有被编码,这里为什么不赋一样的值?
解答: 这里不是表示当前编码的块,而是表示的位置信息 ,这个从赋值关系中可以看出来
先对照宏块里面块的编码数序看
0 1 4 5
2 3 6 7
8 9 12 13
10 11 14 15
(1 )h->mb.i_neighbour4[0 ] =
h->mb.i_neighbour8[0] = (h->mb.i_neighbour & (MB_TOP|MB_LEFT|MB_TOPLEFT))
| ((h->mb.i_neighbour & MB_TOP) ? MB_TOPRIGHT : 0);
0 的左 、上 、左上 、右上 参考块都不确定.但是为什么把 TOPRIGHT单独列出来呢,如上图位置关系,0块就是当TOP有效时,TOPRIGHT才有效。以下同理。
(2) h->mb.i_neighbour4[4 ] =
h->mb.i_neighbour4[1 ] = MB_LEFT
| ((h->mb.i_neighbour & MB_TOP) ? (MB_TOP|MB_TOPLEFT|MB_TOPRIGHT) : 0);
4 、1 的 左 参考块确定,而上 、左上 、右上 参考块都不确定
(3) h->mb.i_neighbour4[2 ] =
h->mb.i_neighbour4[8 ] =
h->mb.i_neighbour4[10 ] =
h->mb.i_neighbour8[2 ] = MB_TOP|MB_TOPRIGHT
| ((h->mb.i_neighbour & MB_LEFT) ? (MB_LEFT|MB_TOPLEFT) : 0);
2、 8、 10 的 上、 右上 参考块确定,而左 、左上 参考块都不确定
(4) h->mb.i_neighbour4[3 ] =
h->mb.i_neighbour4[7 ] =
h->mb.i_neighbour4[11 ] =
h->mb.i_neighbour4[13 ] =
h->mb.i_neighbour4[15 ] =
h->mb.i_neighbour8[3 ] = MB_LEFT|MB_TOP|MB_TOPLEFT;
这里有点让我看不懂,7 、13 、15 好理解,7 、13 、15左 、 上 、 左上 参考块都确定,这里不写右上 (7 、13 、15 的右上 和0的 右上 是不同的,宏块编码顺序和块的编码顺序也是一样的,0 的 右上 是右上角 的宏块,而7 、13 、15 的右上 是右边 的宏块。右边 的宏块总是在左边 的宏块 之后编码 。如下图宏块1 在 宏块2 之前编码 ,宏块3 在 宏块2 之后编码 。)
附宏块的编码顺序(和块是一样的)
0 1
2 3
3 、 11 有点让人看不懂,3 、 11左 、 上 、 左上 、 右上 参考块都确定,为什么和7 、13 、15 放一起呢? 如果看下编码顺序就不难发现了, 3 右上 是 4 ,而 4 是在 3 之后编码 。所以 3右上 参考块是 不确定的 ,也就将 3 和7 、13 、15 放在一起了。(11 同理 )
(5) h->mb.i_neighbour4[5 ] =
h->mb.i_neighbour8[1 ] = MB_LEFT | (h->mb.i_neighbour & MB_TOPRIGHT)
| ((h->mb.i_neighbour & MB_TOP) ? MB_TOP|MB_TOPLEFT : 0);
5 左 参考块确定,上 、 左上 、 右上 参考块都不确定
(6) h->mb.i_neighbour4[6 ] =
h->mb.i_neighbour4[9 ] =
h->mb.i_neighbour4[12 ] =
h->mb.i_neighbour4[14 ] = MB_LEFT|MB_TOP|MB_TOPLEFT|MB_TOPRIGHT;
6 、9 、12、 14 的左 、上 、左上 、右上 参考块都确定
3 另一个问题
来自264乐园的兄弟“遥远”,问我
h->mc.copy[i?PIXEL_8x8:PIXEL_16x16]( h->mb.pic.p_fenc[i], FENC_STRIDE,
&h ->fenc->plane[i][ w * (i_mb_x + i_mb_y * i_stride) ], i_stride, w );
(1 )w * (i_mb_x + i_mb_y * i_stride) 不明白为什么要* w ( 这只考虑i=0情况,即Y情况,U、V类似)
(2)h->mc.copy这个函数定义在哪?
解答:
(1 )汗一个,刚开始我也没弄懂,真是惭愧。i_stride=240 是像素点Y的步长,所以这里坐标表示的是像素点Y的位置,
(i_mb_x + i_mb_y * i_stride) 是每个像素点Y位置的索引,w * (i_mb_x + i_mb_y * i_stride) 是每个宏块Y的索引.
(2)根据h->mc.copy找 copy定义 ,发现带5个参数,直接搜索copy,会发现好多带6个参数,那是不对的,是其他的copy函数。这时要利用i?PIXEL_8x8:PIXEL_16x16这个信息,我找到了
pf->copy[PIXEL_16x16] = mc_copy_w16;
pf->copy[PIXEL_8x8] = mc_copy_w8;
pf->copy[PIXEL_4x4] = mc_copy_w4;
再根据其中一个
pf->copy[PIXEL_16x16] = mc_copy_w16;
我找到了
#define MC_COPY( name, a ) /
static void name( uint8_t *src, int i_src, /
uint8_t *dst, int i_dst, int i_height ) /
{ /
int y; /
for( y = 0; y < i_height; y++ ) /
{ /
memcpy ( dst, src, a ); /
src += i_src; /
dst += i_dst; /
} /
}
MC_COPY( mc_copy_w4, 4 )
MC_COPY( mc_copy_w8, 8 )
MC_COPY( mc_copy_w16, 16 )
应该就是这个了。