分享

Encode

 书城一隅 2011-09-13

static int  Encode( x264_param_t *param, cli_opt_t *opt )

{

    x264_t *h;                                                                          //编码器句柄

    x264_picture_t pic;                                                            //当前编码帧

 

    int     i_frame, i_frame_total;                                              //编码帧数目统计

    int64_t i_start, i_end;                                                         //编码时间统计

    int64_t i_file;                                                                      //当前NAL打包的长度

    int     i_frame_size;                                                             //编码后的码流长度

    int     i_update_interval;                                                     //统计编码信息的间隔长度

    char    buf[200];                                                                 //编码信息 

    opt->b_progress &= param->i_log_level < X264_LOG_DEBUG;                           //调试信息等级

    i_frame_total = p_get_frame_total( opt->hin );                                                //读取输入文件的总帧数

    i_frame_total -= opt->i_seek;

    if( ( i_frame_total == 0 || param->i_frame_total < i_frame_total )

        && param->i_frame_total > 0 )

        i_frame_total = param->i_frame_total;                                                               //总编码帧数目

    param->i_frame_total = i_frame_total;

    i_update_interval = i_frame_total ? x264_clip3( i_frame_total / 1000, 1, 10 ) : 10;//编码信息更新间隔

 

    if( ( h = x264_encoder_open( param ) ) == NULL ) //对不正确的264_t结构体(h的类型是264_t * )参数进行修改,并对各结构体参数、编码、预测等需要的参数进行初始化。

    {

        fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );

        p_close_infile( opt->hin );                                                                                 //关闭YUV文件

        return -1;

    }

 

    if( p_set_outfile_param( opt->hout, param ) )                                                         //设置输出文件格式

    {

        fprintf( stderr, "x264 [error]: can't set outfile param\n" );

        p_close_infile( opt->hin );                                                                                   //关闭YUV文件

        p_close_outfile( opt->hout );                                                                               //关闭码流文件

        return -1;

    }

    /*创建一帧图像空间*/

    if( x264_picture_alloc ( &pic, X264_CSP_I420, param->i_width, param->i_height ) < 0 )

    {

        fprintf( stderr, "x264 [error]: malloc failed\n" );

        return -1;

    }                                    //x264_picture_alloc() 按照色度空间分配内存,并返回内存的首地址作为指针

i_start = x264_mdate();                                                                //用于编码用时的计算,设定起始时间

    /* 循环编码所有帧

利用下面一个for循环,开始一帧一帧进行编码。在这个for循环中,  读取 p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ),  编码并保存 i_file += Encode_frame( h, opt->hout, &pic );

*/

 for( i_frame = 0, i_file = 0; b_ctrl_c == 0 && (i_frame < i_frame_total || i_frame_total == 0); )  

    {

        if( p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ) )

                                 //按照h->hin提供的输入文件的地址,读入图像的内容到&pic提供的存储区的首地址

            break;

        pic.i_pts = (int64_t)i_frame * param->i_fps_den;

 

        if( opt->qpfile )

          parse_qpfile( opt, &pic, i_frame + opt->i_seek );//从指定文件中读qp值留下的接口,qpfile为文件的首地址

        else

        {

            pic.i_type = X264_TYPE_AUTO;

            pic.i_qpplus1 = 0;                                             // 未强制任何编码参数

        }

       /*编码一帧图像,h编码器句柄,hout码流文件,pic预编码帧图像*/

        i_frame_size =Encode_frame( h, opt->hout, &pic );

        if( i_frame_size < 0 )

            return -1;

        i_file += i_frame_size;

        i_frame++;

        /* 更新数据行,用于显示整个编码过程的进度*/

        if( opt->b_progress && i_frame % i_update_interval == 0 )

        {

            int64_t i_elapsed = x264_mdate() - i_start;

            double fps = i_elapsed > 0 ? i_frame * 1000000. / i_elapsed : 0;                                //帧率的计算

            double bitrate = (double) i_file * 8 * param->i_fps_num / ( (double) param->i_fps_den * i_frame * 1000 );

            if( i_frame_total )

            {

                int eta = i_elapsed * (i_frame_total - i_frame) / ((int64_t)i_frame * 1000000);

                sprintf( buf, "x264 [%.1f%%] %d/%d frames, %.2f fps, %.2f kb/s, eta %d:%02d:%02d",

                         100. * i_frame / i_frame_total, i_frame, i_frame_total, fps, bitrate,

                         eta/3600, (eta/60)%60, eta%60 );

            }

            else

            {

                sprintf( buf, "x264 %d frames: %.2f fps, %.2f kb/s", i_frame, fps, bitrate );

            }

            fprintf( stderr, "%s  \r", buf+5 );

            SetConsoleTitle( buf );                                                           //命令行标题设定

            fflush( stderr );                                                                        // 刷新输出缓冲区

        }

    }

    /* 排空延迟的B帧*/

    while( x264_encoder_delayed_frames( h ) )

    {

        i_frame_size = Encode_frame( h, opt->hout, NULL );

        if( i_frame_size < 0 )

            return -1;

        i_file += i_frame_size;

    }

    i_end = x264_mdate();

    x264_picture_clean( &pic );                                                          //申请释放一帧图像控件

    if( opt->b_progress )

        fprintf( stderr, "                                                                               \r" );

    x264_encoder_close( h );                                                            //关闭编码器

    x264_free( mux_buffer );                                                               //释放内存

    fprintf( stderr, "\n" );

    if( b_ctrl_c )                                                                                     //信号中断,显示帧序号

        fprintf( stderr, "aborted at input frame %d\n", opt->i_seek + i_frame );

    p_close_infile( opt->hin );                                                               //关闭输入的YUV文件

    p_close_outfile( opt->hout );                                                           //关闭输出的码流

    if( i_frame > 0 )                                                                               //打印当前的统计信息:fps kbps

    {

        double fps = (double)i_frame * (double)1000000 /

                     (double)( i_end - i_start );

        fprintf( stderr, "encoded %d frames, %.2f fps, %.2f kb/s\n", i_frame, fps,

                 (double) i_file * 8 * param->i_fps_num /

                 ( (double) param->i_fps_den * i_frame * 1000 ) );

    }

  return 0;

}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多