天津市小汽车摇号登陆: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帧随后放入。

还有很多细节,也有很多数据结构不知道怎么个回事,用在哪里,怎么用,只是看见放在里面了,初始化啥的。