x264这个sdk非常棒!
x264源码:
./configure --enable-shared --disable-asm
make
找到pexports源文件
./configure
make
编译出来的pexports.exe是i686平台的。
拷贝pexports.exe放到
D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\bin\Hostx64\x86
打开vs2017开始中的 “VS 2017的x64_x86交叉工具命令提示符”
把libx264-157.dll拷贝到一个独立的文件夹,然后执行:
pexports ./libx264-157.dll > libx264-157.def
再执行:
lib /def:libx264-157.def /machine:x86 /out:libx264-157.lib
把x264的include文件夹拷贝到安装的位置,把其他的libx264-157.dll和libx264-157.lib放到 bin目录和lib目录中。
然后就可以在vs2017的vc项目的x86的release中使用了。
测试环境,下面这个经典的例子已经包含了编码器的主要使用流程,只是参数设置上略显单调,参数的使用需要慢慢掌握。
新建VC 2017的控制台程序,设置为x86项目,配置属性中的 包含目录 和 库目录 以及 链接输入libx264-157.lib:
#include
#include
#include
#include "stdint.h"
extern "C"
{
#include "x264.h"
};
unsigned int g_uiPTSFactor = 0;
int iNal = 0;
x264_nal_t* pNals = NULL;
int encode(x264_t* p264, x264_picture_t* pIn, x264_picture_t* pOut);
int main(int argc, char** argv)
{
int iResult = 0;
x264_t* pX264Handle = NULL;
x264_param_t* pX264Param = new x264_param_t;
assert(pX264Param);
//* 配置为默认参数
x264_param_default(pX264Param);
//* cpuFlags
pX264Param->i_threads = X264_SYNC_LOOKAHEAD_AUTO;
//* video Properties
pX264Param->i_width = 320; //* width
pX264Param->i_height = 240; //* height
pX264Param->i_frame_total = 0; //* 视频总帧数,0表示任意
pX264Param->i_keyint_max = 10;
//* bitstream parameters
pX264Param->i_bframe = 5;
pX264Param->b_open_gop = 0;
pX264Param->i_bframe_pyramid = 0;
pX264Param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
//* 比特流参数
//pX264Param->vui.i_sar_width = 1080;
//pX264Param->vui.i_sar_height = 720;
//* Log参数
pX264Param->i_log_level = X264_LOG_DEBUG;
//* Rate control Parameters
pX264Param->rc.i_bitrate = 1024 * 10;//* 码率(Kbps)
//* muxing parameters
pX264Param->i_fps_den = 1; //* 帧率分母
pX264Param->i_fps_num = 25;//* 帧率分子
pX264Param->i_timebase_den = pX264Param->i_fps_num;
pX264Param->i_timebase_num = pX264Param->i_fps_den;
//* 设置编码等级profile : baseline、main、height ( 直播baseline:流畅 、Main:有停顿现象 、本地FLV文件:main)
x264_param_apply_profile(pX264Param, x264_profile_names[1]);
//* 创建264编码器。后面可以使用x264_encoder_parameters来编码器参数,可以使用x264_encoder_reconfig更新设置参数
pX264Handle = x264_encoder_open(pX264Param);
assert(pX264Handle);
//* 获取流的PPS和SPS
iResult = x264_encoder_headers(pX264Handle, &pNals, &iNal);
assert(iResult >= 0);
//* PPS SPS 解析
for (int i = 0; i < iNal; ++i)
{
switch (pNals[i].i_type)
{
case NAL_SPS:
break;
case NAL_PPS:
break;
default:
break;
}
}
//* 编码器缓存的最大帧数
int iMaxFrames = x264_encoder_maximum_delayed_frames(pX264Handle);
//* 编码需要的临时变量
iNal = 0;
pNals = NULL;
x264_picture_t* pPicIn = new x264_picture_t;
x264_picture_t* pPicOut = new x264_picture_t;
x264_picture_init(pPicOut);
x264_picture_alloc(pPicIn, X264_CSP_I420, pX264Param->i_width, pX264Param->i_height);
pPicIn->img.i_csp = X264_CSP_I420;
pPicIn->img.i_plane = 3;
//* 创建264本地视频文件
FILE* pFile;
fopen_s(&pFile,"d:\\hellox264.264", "wb");
assert(pFile);
//* 一帧中YUV420中Y的数据长度
int iDataLen = pX264Param->i_width * pX264Param->i_height;
uint8_t* data = new uint8_t[iDataLen];
unsigned int uiComponent = 0;
while (++uiComponent<1030)
{
//* 每一帧的数据构成YUV420
::memset(data, uiComponent, iDataLen);
::memcpy(pPicIn->img.plane[0], data, iDataLen);
::memcpy(pPicIn->img.plane[1], data, iDataLen / 4);
::memcpy(pPicIn->img.plane[2], data, iDataLen / 4);
if (uiComponent <= 1000)
{
pPicIn->i_pts = uiComponent + g_uiPTSFactor * 1000;
encode(pX264Handle, pPicIn, pPicOut);
}
else
{
int iResult = encode(pX264Handle, NULL, pPicOut);
if (0 == iResult)
{
//uiComponent = 0;
++g_uiPTSFactor;
}
}
//* 编码完成的多帧数据逐一写入视频文件
for (int i = 0; i < iNal; ++i)
{
fwrite(pNals[i].p_payload, 1, pNals[i].i_payload, pFile);
}
}
//* 释放清除图像数据
x264_picture_clean(pPicIn);
// x264_picture_clean(pPicOut);
//* 利用句柄关闭解码器
x264_encoder_close(pX264Handle);
pX264Handle = NULL;
delete pPicIn;
pPicIn = NULL;
delete pPicOut;
pPicOut = NULL;
delete pX264Param;
pX264Param = NULL;
delete[] data;
data = NULL;
return 0;
}
int encode(x264_t* pX264Handle, x264_picture_t* pPicIn, x264_picture_t* pPicOut)
{
int iResult = 0;
iResult = x264_encoder_encode(pX264Handle, &pNals, &iNal, pPicIn, pPicOut);
if (0 == iResult)
{
std::cout << "编码成功,但是缓存在编码器中" << std::endl;
}
else
if (iResult < 0)
{
std::cout << "编码出错" << std::endl;
}
else
if (iResult > 0)
{
std::cout << "编码成功,并需要写入视频文件流" << std::endl;
}
int iFrames = x264_encoder_delayed_frames(pX264Handle);
std::cout << "缓冲帧数:" << iFrames << "\n";//因为要进行编码,所以编码器需要缓存很多帧才好生成I、P、B帧
return iFrames;
}