如何利用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函数中)
经与H.264visa提取的结果进行对比,发现上面的代码提取的结果完全正确. OK, 到此为止,P帧运动矢量的提取总算大功告成.
之前已经讨论过提取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帧运动矢量的提取总算大功告成.
相关文章推荐
- 如何利用JM8.6解码器提取码流中P帧宏块(第一个4*4块)的运动矢量(考虑B帧,设x264编码的12帧为IDR BBPBBPBBPBP)
- 如何利用JM8.6解码器提取码流中P帧宏块的运动矢量(假设编码不用B帧,仅为IDR P P)
- 如何在JM8.6代码的编码端提取残差(为简便起见,仅以I4x4宏块为例)
- 如何用JM8.6将所有的帧都编码为I帧?
- 如何在JM8.6代码的编码端提取残差(为简便起见,仅以I4x4宏块为例)
- 如何在JM8.6中设置编码帧类型为IDR B B P B B P B B P B B I B B P...?
- live555+ffmpeg如何提取关键帧(I帧,P帧,B帧)
- JM8.6解码端是如何对H.264码流进行读取的?(GetAnnexbNALU 函数)
- live555+ffmpeg如何提取关键帧(I帧,P帧,B帧)
- JM8.6中NALU(此处指VCL式的NALU)是如何写进码流的?
- 如何在JM8.6编码端提取QDCT?
- live555+ffmpeg如何提取关键帧(I帧,P帧,B帧)
- 如何从JM8.6的编码端和解码端提取滤波前的像素值?
- 如何在JM8.6编码端提取QDCT?
- JM8.6代码中究竟是如何把码流写进test.264文件的?
- live555+ffmpeg如何提取关键帧(I帧,P帧,B帧)
- 如何从H.264码流中确定每个P帧中有多少I宏块?
- 【zz】live555+ffmpeg如何提取关键帧(I帧,P帧,B帧)
- live555+ffmpeg如何提取关键帧(I帧,P帧,B帧)
- live555+ffmpeg如何提取关键帧(I帧,P帧,B帧)