x264的编码示例
/**
?* @note x264的編碼示例.
?* 使用x264的版本為libx264-115
?* 1. 示例是個死循環,會源源不斷的編碼,然后將數據寫文件.
?* 2. 示例的行為是:編碼1000幀后,取空編碼緩沖區,然后循環執行這兩步.
#include <cassert>
#include <iostream>
#include <string>
#include "stdint.h"
#include <string.h>
#include <stdio.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; //* 寬度.
pX264Param->i_height = 240; //* 高度
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.使用MainProfile
x264_param_apply_profile(pX264Param, x264_profile_names[1]);
//* 打開編碼器句柄,通過x264_encoder_parameters得到設置給X264
//* 的參數.通過x264_encoder_reconfig更新X264的參數
pX264Handle = x264_encoder_open(pX264Param);
assert(pX264Handle);
//* 獲取整個流的PPS和SPS,不需要可以不調用.
iResult = x264_encoder_headers(pX264Handle, &pNals, &iNal);
assert(iResult >= 0);
//* PPS SPS 總共只有36B,如何解析出來呢?
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;
//* 創建文件,用于存儲編碼數據
FILE* pFile = fopen("agnt.264", "wb");
assert(pFile);
//* 示例用編碼數據.
int iDataLen = pX264Param->i_width * pX264Param->i_height;
uint8_t* data = new uint8_t[iDataLen];
unsigned int uiComponent = 0;
while (++uiComponent) {
//* 構建需要編碼的源數據(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) {
//break; //* 取空,跳出
uiComponent = 0;
++g_uiPTSFactor;
/* {{ 這個解決不了取空緩沖區,再壓縮無B幀的問題
x264_encoder_reconfig(pX264Handle, pX264Param);
x264_encoder_intra_refresh(pX264Handle);
//* }} */
}
}
//* 將編碼數據寫入文件.
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;
}
/* {{ 作用不明
unsigned char* pNal = NULL;
for (int i = 0;i < iNal; ++i)
{
int iData = 1024 * 32;
x264_nal_encode(pX264Handle, pNal,&pNals[i]);
}
//* }} */
//* 獲取X264中緩沖幀數.
int iFrames = x264_encoder_delayed_frames(pX264Handle);
std::cout << "當前編碼器中緩存數據:" << iFrames << "幀\n";
return iFrames;
}
?* @note x264的編碼示例.
?* 使用x264的版本為libx264-115
?* 1. 示例是個死循環,會源源不斷的編碼,然后將數據寫文件.
?* 2. 示例的行為是:編碼1000幀后,取空編碼緩沖區,然后循環執行這兩步.
?* @author?
*gcc ?-lx264
?**/#include <cassert>
#include <iostream>
#include <string>
#include "stdint.h"
#include <string.h>
#include <stdio.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; //* 寬度.
pX264Param->i_height = 240; //* 高度
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.使用MainProfile
x264_param_apply_profile(pX264Param, x264_profile_names[1]);
//* 打開編碼器句柄,通過x264_encoder_parameters得到設置給X264
//* 的參數.通過x264_encoder_reconfig更新X264的參數
pX264Handle = x264_encoder_open(pX264Param);
assert(pX264Handle);
//* 獲取整個流的PPS和SPS,不需要可以不調用.
iResult = x264_encoder_headers(pX264Handle, &pNals, &iNal);
assert(iResult >= 0);
//* PPS SPS 總共只有36B,如何解析出來呢?
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;
//* 創建文件,用于存儲編碼數據
FILE* pFile = fopen("agnt.264", "wb");
assert(pFile);
//* 示例用編碼數據.
int iDataLen = pX264Param->i_width * pX264Param->i_height;
uint8_t* data = new uint8_t[iDataLen];
unsigned int uiComponent = 0;
while (++uiComponent) {
//* 構建需要編碼的源數據(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) {
//break; //* 取空,跳出
uiComponent = 0;
++g_uiPTSFactor;
/* {{ 這個解決不了取空緩沖區,再壓縮無B幀的問題
x264_encoder_reconfig(pX264Handle, pX264Param);
x264_encoder_intra_refresh(pX264Handle);
//* }} */
}
}
//* 將編碼數據寫入文件.
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;
}
/* {{ 作用不明
unsigned char* pNal = NULL;
for (int i = 0;i < iNal; ++i)
{
int iData = 1024 * 32;
x264_nal_encode(pX264Handle, pNal,&pNals[i]);
}
//* }} */
//* 獲取X264中緩沖幀數.
int iFrames = x264_encoder_delayed_frames(pX264Handle);
std::cout << "當前編碼器中緩存數據:" << iFrames << "幀\n";
return iFrames;
}
總結
- 上一篇: Android C/C++ 开发
- 下一篇: socket和IOCTL结合实现网络采集