文章详情

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

x264源代码分析(二)

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

这个函数前面有一段注释(如下):

****************************************************************************

 * x264_encoder_encode:

 *  XXX: i_poc   : is the poc of the current given picture

 *       i_frame : is the number of the frame being coded

 *  ex:  type frame poc

 *       I      0   2*0//poc是实际的帧的位置.

 *       P      1   2*3//frame是编码的顺序.

 *       B      2   2*1

 *       B      3   2*2

 *       P      4   2*6

 *       B      5   2*4

 *       B      6   2*5

 ****************************************************************************/

要搞清poc和frame的区别.

假设一个视频序列如下:

I     B    B    P     B     B     P

我们编码是按I  P  B  B  P  B  B的顺序,这就是frame的编号.

而我们视频序列的播放序号是POC的序号,这里是乘以了2.

函数中先定义了如下三个参数:

int     i_nal_type; 

nal存放的数据类型, 可以是sps,pps等多种.                  

int     i_nal_ref_idc;

nal的优先级,nal重要性的标志位.

前面两个参数虽然简单,但如果不参照标准,也不容易理解,所以标准中的句法表是很重要的,可以说是最关键的.

int     i_slice_type;

slice的类型,在x264中我的感觉好像一帧只有一个slice.如果确定了帧的类型,slice的类型也就确定了.

 

我们来看看编码器是如何区分读入的一帧是I帧,P帧,或者B帧,这个过程需要好好理解.

还以I     B  B  P    B   B     P为例.

 

if( h->i_frame % (h->param.i_iframe * h->param.i_idrframe) == 0 ){

确定这是立即刷新片.

}

         这里很好理解.

但到了if( h->param.i_bframe > 0 )//可以B帧编码时.

就有问题了.

注意我们编完I帧后碰到了一个B帧,这时我们先不对它进编码.而是采用frame = x264_encoder_frame_put_from_picture( h, h->frame_next, pic )函数将这个B帧放进h->frame_next中.

好,这里出现了h->frame_next,在h中同时定义了下面几个帧数组用以实现帧的管理.

x264_frame_t   *bframe_current[X264_BFRAME_MAX]; /* store the sequence of b frame being encoded */

    x264_frame_t    *frame_next[X264_BFRAME_MAX+1];   /* store the next sequence of frames to be encoded *///搞清意义,下一个帧,而不一定是B帧.

    x264_frame_t    *frame_unused[X264_BFRAME_MAX+1]; /* store unused frames */

注意区分这3个数组.

同时还有下面4个函数(定义在\ENCODER\encoder.c中).

x264_encoder_frame_put_from_picture();

x264_encoder_frame_put();

x264_encoder_frame_get();

x264_frame_copy_picture();

这3个数组和4个函数可以说完成了整个帧的类型的判定问题.这个里面if ,else语句较多,容易使人迷惑.但我们只要把握下面一个观点就可以看清实质:在不对P帧进行编码之前,我们不对B帧进行编码,只是把B帧放进缓冲区(就是前面提到的数组).

比如视频序列:I     B  B  P  B  B  P

先确立第一个帧的类型,然后进行编码.然后是2个B帧,我们把它放进缓冲区数组.然后是P帧,我们可以判定它的类型并进行编码.同时,我们将缓冲区的B帧放进h->bframe_current[i],不过这时P帧前的两个B帧并没有编码.当读到P帧后面的第一个B帧时,我们实际上才将h->bframe_current数组中的第一个B帧编码,也就是将在I帧后面的第一个B帧(说成P帧前面的第一个B帧容易误解J)编码.

依此类推,把握好上面4个函数的调用流程和指针操作的用法,就可以将帧的类型判定这个问题搞明白了.

F.      然后是速率控制(先不说这个,因为它对编码的流程影响不大),看看建立参考帧列表的操作,也就是

x264_reference_build_list( h, h->fdec->i_poc ); (定义在\ENCODER\encoder.c中).

光看这个函数是不行的,它是和后面的这个函数(如下)一起配合工作的.

if( i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE )//B帧时.

    {

        x264_reference_update( h );

}

     If条件是判断当前帧是否是B帧,如果是的话就不更新参考列表,因为B帧本来就不能作为参考帧嘛!如果是I帧或P帧的话,我们就更新参考帧列表.

我们看到了一个for循环,两个do—while循环.这是实现的关键,具体看代码,不好用语言说明白.

 

G.     进入另一个复杂的领域:写slice的操作,刚开使挺简单,如我下面的注释.

/* ---------------------- Write the bitstream -------------------------- */

    /* Init bitstream context */

    h->out.i_nal = 0;//out的声明在bs.h中.

    bs_init( &h->out.bs, h->out.p_bitstream, h->out.i_bitstream );//空出8位.

 

    /* Write SPS and PPS */

    if( i_nal_type == NAL_SLICE_IDR )//不是每次都要写SPS and PPS,只有碰见立即刷新片时才写.

    {

        /* generate sequence parameters */

        x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );

        x264_sps_write( &h->out.bs, h->sps );

        x264_nal_end( h );

 

        /* generate picture parameters */

        x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );

        x264_pps_write( &h->out.bs, h->pps );

        x264_nal_end( h );

}

不过看下面那个函数(就进入了复杂的领域).

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

萌趣贪吃蛇

休闲益智 下载
粘液快跑

粘液快跑

休闲益智 下载
一个不能跑

一个不能跑

休闲益智 下载