天津市小汽车摇号登陆:x264源码阅读笔记1
来源:百度文库 编辑:中财网 时间:2024/05/06 12:55:10
x264源码阅读笔记1
终于有时间读源码了,终于有时间写点心得了,省得以后看过就忘,记的虽然没啥东西,只是为了过了几个月后知道自己曾经看过X264源码吧。
开始好几天不知从何入手,前几天终于把那几个参考帧队列是咱么回事看了个大概,就简单说说吧。虽然网上有很多人读过了也写过编码流程啥的,但是自己看了都基本上是不知所云,自己的东西应该用自己的语言写出来。所以我就用自己的语言,或大白话记录下。
刚开始那些分析输入参数,就不说了,就是Parse那里的。直接从读取文件中一帧一帧的图像数据开始吧,就是直接到了i_file += Encode_frame( h, opt->hout, &pic );进去后有个if( x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out ) < 0 );这里就开始了:
if( pic_in != NULL )
{
/* 1: Copy the picture to a frame and move it to a buffer */
x264_frame_t *fenc = x264_frame_get( h->frames.unused );
x264_frame_copy_picture( h, fenc, pic_in );
if( h->param.i_width % 16 || h->param.i_height % 16 )
x264_frame_expand_border_mod16( h, fenc );
fenc->i_frame = h->frames.i_input++;
x264_frame_put( h->frames.next, fenc );
if( h->frames.b_have_lowres )
x264_frame_init_lowres( h->param.cpu, fenc );
if( h->frames.i_input <= h->frames.i_delay )
{
/* Nothing yet to encode */
/* waiting for filling bframe buffer */
pic_out->i_type = X264_TYPE_AUTO;
return 0;
}
}
if( h->frames.current[0] == NULL )
{
int bframes = 0;
/* 2: Select frame types */
if( h->frames.next[0] == NULL )
return 0;
x264_slicetype_decide( h );
/* 3: move some B-frames and 1 non-B to encode queue */
while( IS_X264_TYPE_B( h->frames.next[bframes]->i_type ) )
bframes++;
x264_frame_put( h->frames.current, x264_frame_get( &h->frames.next[bframes] ) );
/* FIXME: when max B-frames > 3, BREF may no longer be centered after GOP closing */
if( h->param.b_bframe_pyramid && bframes > 1 )
{
x264_frame_t *mid = x264_frame_get( &h->frames.next[bframes/2] );
mid->i_type = X264_TYPE_BREF;
x264_frame_put( h->frames.current, mid );
bframes--;
}
while( bframes-- )
x264_frame_put( h->frames.current, x264_frame_get( h->frames.next ) );
}
这部分就是那个current队列和next队列,next队列里的frame依据啥规则放到了current队列里。current队列就是当前要编码的队列,前面的就是要先编码,下面有句话:
/* ------------------- Get frame to be encoded ------------------------- */
/* 4: get picture to encode */
h->fenc = x264_frame_get( h->frames.current );
就是取出current队列里的第一个frame进行编码拉,而next队列则是帧的原始顺序,current队列里的frame顺序不是帧的原始顺序而是要编码的顺序,有B帧的时候要先编码B后面的参考帧,这些不多说了。
好,回到那一大堆代码开始(有点象GOTO。。。),先看:
/* 1: Copy the picture to a frame and move it to a buffer */
x264_frame_t *fenc = x264_frame_get( h->frames.unused );
x264_frame_copy_picture( h, fenc, pic_in );
if( h->param.i_width % 16 || h->param.i_height % 16 )
x264_frame_expand_border_mod16( h, fenc );
fenc->i_frame = h->frames.i_input++;
x264_frame_put( h->frames.next, fenc );
把从视频序列里取出的pic_in,拷贝要编码的图像信息,或者说是数据信息,放在unused队列里,那里面存放帧的个数据结构和 next,current存放帧的数据结构一样。然后把它再put到next队列里。插一下,x264_frame_put是从后面加,x264_frame_get是从前面取,还有个方法x264_frame_push,是从前面加。
然后是next到current的过程:
/* 2: Select frame types */
if( h->frames.next[0] == NULL )
return 0;
x264_slicetype_decide( h );
/* 3: move some B-frames and 1 non-B to encode queue */
while( IS_X264_TYPE_B( h->frames.next[bframes]->i_type ) )
bframes++;
x264_frame_put( h->frames.current, x264_frame_get( &h->frames.next[bframes] ) );
/* FIXME: when max B-frames > 3, BREF may no longer be centered after GOP closing */
if( h->param.b_bframe_pyramid && bframes > 1 )
{
x264_frame_t *mid = x264_frame_get( &h->frames.next[bframes/2] );
mid->i_type = X264_TYPE_BREF;
x264_frame_put( h->frames.current, mid );
bframes--;
}
while( bframes-- )
x264_frame_put( h->frames.current, x264_frame_get( h->frames.next ) );
首先判断此帧应该的类型,里面判断应该是I,P还是B帧,怎么算的先不说,然后如果是有B帧,则把B帧后的第一个参考帧,放入current里,然后x264_frame_put( h->frames.current, x264_frame_get( h->frames.next ) );把B帧随后放入。
还有很多细节,也有很多数据结构不知道怎么个回事,用在哪里,怎么用,只是看见放在里面了,初始化啥的。