您的位置:首页 > 其它

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

2012-12-30 20:19 369 查看
       说明:有好心的读者对下面程序提出了质疑,我觉得有道理,有兴趣的读者可以看看文章后面的评论。感谢那位提出质疑的读者,同时也欢迎各位批评指正。

       之前已经讨论过提取P帧各个宏块的第一个4*4块对应的运动矢量,现在考虑提取所有4*4块的运动矢量. 我们知道,在H.264中,宏块是有分块的的,不同情况下分块方式不一样,所以与MPEG2不同,每一个宏块并不只是对应一个运动矢量. 而由于分块的复杂性和多样性,我们可以这样认为:每个4*4块都有一个运动矢量. 比如,对于一个P-skip宏块而言,尽管运动矢量只有一个,但我们认为该宏块的每个4*4块都有一个运动矢量.

 

        在P帧中,为了处理方便,本人认为I宏块有运动矢量,其值为零. 在P帧中,有3种基本的宏块:I宏块,skip形式的P宏块和非skip形式的P宏块. 对于前面两种宏块,仅有唯一的运动矢量,因此提取其每个4*4块的运动矢量时,只需要把一个运动矢量重复16次就OK了,很简单,搞一个16次的循环就可以了,但对于非skip形式的P宏块则相对复杂,因为分块不同, 所以在写的时候要特别注意. 下面仅仅给出提取非skip形式的P宏块的运动矢量的代码: (该代码在readMotionInfoFromNAL函数中)

// 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就是运动矢量
vec=curr_mvd+pmv[k];           /* find motion vector */

// myFlag用作标记
// buffer数组用作保存运动矢量的x分量和y分量
// buffer[0]存x分量,buffer[1]存y分量
if(myFlag < 2)
buffer[myFlag++] = vec;
if(2 == myFlag)
{
// 一个运动矢量对应的块数为step_h * step_v
for(ii=0; ii < step_h * step_v; ii++)
{
if(img->type == P_SLICE) // 保证是P帧(片)
{
fprintf(myMV, "%-4d %-4d ", buffer[0], buffer[1]);
}
}
myFlag = 0;
}

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;
}
}
}

      

      经与H.264visa提取的结果进行对比,发现上面的代码提取的结果完全正确. OK, 到此为止,P帧运动矢量的提取总算大功告成.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: