文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>x264源代码分析(三)

x264源代码分析(三)

时间:2006-07-17  来源:lzhw_lucky

H.     x264_slice_write()(定义在\ENCODER\encoder.c中),这里面是编码的最主要部分,下面仔细分析.

前面不说,看下面这个循环,它是采用for循环对一帧图像的所有块依次进行编码.

for( mb_xy = 0, i_skip = 0; mb_xy < h->sps->i_mb_width * h->sps->i_mb_height; mb_xy++ )//h->sps->i_mb_width指的是从宽度上说有多少个宏快.对于宽度也就是288 / 16 = 18

    {

        const int i_mb_y = mb_xy / h->sps->i_mb_width;

        const int i_mb_x = mb_xy % h->sps->i_mb_width;//这两个变量是定义宏块的位置.而不是指宏块中元素的位置.

 

        /* load cache */

        x264_macroblock_cache_load( h, i_mb_x, i_mb_y );//是把当前宏块的up宏块和left宏块的intra4x4_pred_mode,non_zero_count加载进来,放到一个数组里面,这个数组用来直接得到当前宏块的左侧和上面宏块的相关值.要想得到当前块的预测值,要先知道上面,左面的预测值,它的目的是替代getneighbour函数.

/* analyse parameters

         * Slice I: choose I_4x4 or I_16x16 mode

         * Slice P: choose between using P mode or intra (4x4 or 16x16)

         * */

        TIMER_START( i_mtime_analyse );

        x264_macroblock_analyse( h );//定义在analyse.h中.

        TIMER_STOP( i_mtime_analyse );

 

        /* encode this macrobock -> be carefull it can change the mb type to P_SKIP if needed */

        TIMER_START( i_mtime_encode );

        x264_macroblock_encode( h );//定义在Enc/encoder.c中.

        TIMER_STOP( i_mtime_encode );

截止到这就已经完成编码的主要过程了,后面就是熵编码的过程了(我也没看到那,但认为前面才是编码的主要过程).下面对这个过程进行分析.

A.     x264_macroblock_cache_load( h, i_mb_x, i_mb_y );它是将要编码的宏块的周围的宏块的值读进来, 要想得到当前块的预测值,要先知道上面,左面的预测值,它的作用相当于jm93中的getneighbour函数.

B.      进入x264_macroblock_analyse( h )函数(定义在\Enc\analyse.c中,这里涉及到了函数指针数组,需要好好复习,个人认为这也是x264代码最为复杂的一个地方了).既然已经将该宏块周围的宏块的值读了出来,我们就可以对该宏块进行分析了(其实主要就是通过计算sad值分析是否要将16*16的宏块进行分割和采用哪种分割方式合适).

看似很复杂,但我们只要把握一个东西就有利于理解了:

举个生活中的例子来说:

如果你有2元钱,你可以去买2袋1元钱的瓜子,也可以买一袋2元钱的瓜子,如果2袋1元钱的瓜子数量加起来比1袋2元钱的瓜子数量多,你肯定会买2袋1元的.反之你会去买那2元1袋的.

具体来说,对于一个16*16的块,

如果它是I帧的块,我们可以将它分割成16个4*4的块,如果这16个块的sad加起来小于按16*16的方式计算出来的sad值,我们就将这个16*16的块分成16个4*4的块进行编码(在计算每个4*4的块的最小sad值时已经知道它采用何种编码方式最佳了),否则采用16*16的方式编码(同样我们也已知道对它采用哪种编码方式最为合适了.

如果它是P帧或B帧的块,同样是循环套循环,但更为复杂了,可以看我在analyse.c中的注释.

这里还要注意的是提到了

x264_predict_t      predict_16x16[4+3];

typedef void (*x264_predict_t)( uint8_t *src, int i_stride );

这是函数指针数组,有很多对它的调用.

C.     退出x264_macroblock_analyse( h )函数,进入x264_macroblock_encode( )函数(定义在\ENCODER\macroblock.c中).

我拿宏块类型为I_16*16为例.

if( h->mb.i_type == I_16x16 )

    {

        const int i_mode = h->mb.i_intra16x16_pred_mode;

        /* do the right prediction */

        h->predict_16x16[i_mode]( h->mb.pic.p_fdec[0], h->mb.pic.i_fdec[0] );//这两个参数的关系.

                                                                   //涉及到x264_predict_t(函数指针数组),声明在core/predict.h中,core/predict.c里有不同定义.

        /* encode the 16x16 macroblock */

        x264_mb_encode_i16x16( h, i_qscale );//

/* fix the pred mode value */

       …     }

我们看到h->predict_16x16[i_mode]( h->mb.pic.p_fdec[0], h->mb.pic.i_fdec[0] );只调用了一次,这是因为在x264_macroblock_analyse(  )中我们已经确定了采用4种方式中的哪种最合适.而在x264_macroblock_analyse(  )中判定一个块是否为I_16*16,我们调用了四次.这是因为当时我们需要拿最小的sad值进行比较.

继续,是x264_mb_encode_i16x16( h, i_qscale )函数(定义在\ENCODER\macroblock.c中).在这个函数中我们就可以看到量化,zig-扫描等函数了,这些都是直来直去的,需要的只是我们的细心和对数学知识的掌握了

相关阅读 更多 +
排行榜 更多 +
萌趣贪吃蛇

萌趣贪吃蛇

休闲益智 下载
粘液快跑

粘液快跑

休闲益智 下载
火柴人超级战车安卓版

火柴人超级战车安卓版

飞行射击 下载