废了我4天总算在win平台下 QT上实现x264编码成功,对于那个bug 认为还是要先了解程序的原理才好排错,但是正是这个bug让我学到了很多,学会了如何可以将lib编译成可以包含调试信息,学会了在VS下反编码,学会了extern "C" 的作用,学会了VS里面牛b的汇编编码……
第一步
上面两步带我走进了x264编码谢谢那个作者:一个健忘症患者的记忆备份
下面才是我学习中的一点bug:
1 注意那个y4m.c 文件在上面那个博客里面
2 那个程序我修改了如下:可以直接复制(我的平台 win64 QT5.3.1 库x264-snapshot-20140803-2245)y4m.c用那个作者的
\ #include <QCoreApplication> #include "stdint.h"//处理字符定义的 //stdint.h是c99中引进的一个标准C库的头文件. extern "C" { #include <assert.h> #include "x264.h" #include "x264_config.h" #include "y4m.c" } #include "iostream" #include "time.h" using namespace std; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); int iResult = 0; x264_t* pX264Handle = NULL; //编码器句柄 x264_param_t* pX264Param = new x264_param_t;//x264_param_t为结构体的名字,见文件X264.h // x264_param_default(pX264Param); assert(pX264Param); //* 配置参数 //* 使用默认参数,在这里因为我的是实时网络传输,所以我使用了zerolatency(零延迟)的选项,使用这个选项之后就不会有delayed_frames,如果你使用的不是这样的话,还需要在编码完成之后得到缓存的编码帧 int res=x264_param_default_preset(pX264Param,"veryfast" , "zerolatency");//"veryfast" //* cpuFlags // pX264Param->i_threads = X264_SYNC_LOOKAHEAD_AUTO;//* 取空缓冲区继续使用不死锁的保证. //* 视频选项 pX264Param->i_width = 384; //* 要编码的图像宽度. pX264Param->i_height = 288; //* 要编码的图像高度 pX264Param->i_frame_total = 0; //* 编码总帧数.不知道用0. pX264Param->i_keyint_max = 10; //* 流参数 pX264Param->i_bframe = 5; pX264Param->b_open_gop = 0; pX264Param->i_bframe_pyramid = 1; pX264Param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS; //* Log参数,不需要打印编码信息时直接注释掉就行 pX264Param->i_log_level = X264_LOG_DEBUG; //X264_LOG_NONE //* 速率控制参数 pX264Param->rc.i_bitrate = 1024 * 10;//* 码率(比特率,单位Kbps) //* muxing parameters pX264Param->i_fps_den = 1; //* 帧率分母 pX264Param->i_fps_num = 10;//* 帧率分子 pX264Param->i_timebase_den = pX264Param->i_fps_num; pX264Param->i_timebase_num = pX264Param->i_fps_den; //* 设置Profile.使用Baseline profile int res2= x264_param_apply_profile(pX264Param, x264_profile_names[0]); //* 编码需要的辅助变量 int iNal = 0; //修改部分 x264_nal_t *pNals = NULL; //修改部分 x264_picture_t* pPicIn = new x264_picture_t; x264_picture_t* pPicOut = new x264_picture_t; x264_picture_init(pPicOut); //输出图像的初始化 int res3= x264_picture_alloc(pPicIn, X264_CSP_I420, pX264Param->i_width, pX264Param->i_height); //输入图像分配数据 pPicIn->img.i_csp = X264_CSP_I420; //设置初始化图片格式 YUV420p pPicIn->img.i_plane = 3; //用于保存YUV分量 //* 打开编码器句柄,通过x264_encoder_parameters得到设置给X264 //* 的参数.通过x264_encoder_reconfig更新X264的参数 pX264Handle = x264_encoder_open(pX264Param); cout<<"pX264Param:"<<sizeof(pX264Param)<<endl; assert(pX264Handle); //* 创建文件,用于存储编码数据 FILE* pFile = fopen("test.264", "wb"); assert(pFile); //设置y4m文件参数 y4m_input_t *y4m_hnd = (y4m_input_t*)malloc(sizeof(y4m_input_t)); //打开y4m文件 iResult = open_file_y4m("example1_352x288.y4m",(hnd_t**)&y4m_hnd,pX264Param); if(iResult < 0 ) { printf("Failed to open file y4m!\n"); system("PAUSE"); return 0; } //得到文件总得帧数 int nFrames = ::get_frame_total_y4m((hnd_t*)y4m_hnd);//9150 cout<<"*************"<<nFrames<<"*************"<<endl; //printf( "start: %ld ms\n", start ); //开始编码 for(int i = 0; i < nFrames;i++ ) { //读取一帧 // i++; read_frame_y4m(pPicIn,(hnd_t*)y4m_hnd,i); if( i ==0 ) pPicIn->i_pts = i; else pPicIn->i_pts = i - 1; //编码 int frame_size = x264_encoder_encode(pX264Handle,&pNals,&iNal,pPicIn,pPicOut); cout<<"frame_size"<<frame_size<<endl; if(frame_size >0) { for (int i = 0; i < iNal; ++i) {//将编码数据写入文件. fwrite(pNals[i].p_payload, 1, pNals[i].i_payload, pFile); } } } //} //* 清除图像区域 // x264_picture_clean(pPicIn); //* 关闭编码器句柄 // x264_encoder_close(pX264Handle); pX264Handle = NULL; delete pPicIn ; pPicIn = NULL; delete pPicOut; pPicOut = NULL; delete pX264Param; pX264Param = NULL; return a.exec(); }我的修改部分:
//* 视频选项 pX264Param->i_width = 384; //* 要编码的图像宽度. pX264Param->i_height = 288; //* 要编码的图像高度
<pre name="code" class="cpp"> //* 编码需要的辅助变量 int iNal = 0; //修改部分 x264_nal_t *pNals = NULL; //修改部分
如果想单步调试进源码时
用这句话configure--enable-shared --enable-debug
替代
configure--enable-shared