x265是一个开源的H.265编码库。API接口方面与x264很相像。本文介绍其在x86 linux及windows 7的编译方法,并给出实例。
一、编译
1、Linux平台
x265编译需要使用到yasm,到http://www.tortall.net/projects/yasm/releases/下载,最新版本为1.3.1。编译命令如下:
# ./configure;make;make install
x265库下载:https://bitbucket.org/multicoreware/x265/downloads,最新版本为1.7。
解压后,进入源码目录的build目录,选择linux。
# cd x265_1.7/build/linux
# ./make-Makefiles.bash
配置如下:
BIN_INSTALL_DIR /home/latelee/bin/x265-1.7
CHECKED_BUILD OFF
CMAKE_BUILD_TYPE Release
CMAKE_INSTALL_PREFIX /home/latelee/bin/x265-1.7
DETAILED_CU_STATS OFF
ENABLE_AGGRESSIVE_CHECKS OFF
ENABLE_ASSEMBLY ON
ENABLE_CLI ON
ENABLE_PIC OFF
ENABLE_PPA OFF
ENABLE_SHARED OFF # 不要动态库
ENABLE_TESTS OFF
ENABLE_VTUNE OFF
ENABLE_SHARED: Build shared library
Press [enter] to edit option CMake Version 3.3.1
Press [c] to configure
Press [h] for help Press [q] to quit without generating
Press [t] to toggle advanced mode (Currently Off)
按c配置,再按g保存并退出。
2、Windows平台
0、安装cmake的windows版本,地址:http://www.cmake.org/download/。在安装过程要记得添加cmake到PATH。
1、进入build目录,根据编译器版本选择不同的工程目录,比如64bit的VS2010,就进入vc10-x86_64目录。双击:build-all.bat。
2、之后出现配置界面时,点击configure,再点击generate,然后关闭窗口。其它不同做。
3、等待cmd窗口编译完成,完成后会自动关闭。
4、在Debug或Release目录找到h265编码器x265.exe,另外还有dll和lib文件。头文件要到源码中找。
注:编译Windows平台,纯粹是为了得到x265,exe文件。
二、实例
下面给出使用的示例。
/**
x265库编码要使用以下库
-lpthread -ldl
ffprobe信息:
Input #0, hevc, from 'test.h265':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: hevc (Main), yuv420p(tv), 176x144, 25 fps, 25 tbr, 1200k
tbn, 25 tbc
*/
#include <stdio.h>
#include <stdlib.h>
#include "x265.h"
int x265_encode(const char* infile, int width, int height, int type, const char* outfile)
{
FILE *fp_src = NULL;
FILE *fp_dst = NULL;
unsigned int luma_size = 0;
unsigned int chroma_size = 0;
//int buff_size = 0;
char *buff = NULL;
uint32_t i_nal=0;
int i_frame=0;
int ret = 0;
x265_param param;
x265_nal *nal = NULL;
x265_encoder *handle = NULL;
x265_picture *pic_in = NULL;
int csp = type; // X265_CSP_I420;
fp_src = fopen(infile, "rb");
fp_dst = fopen(outfile, "wb");
if(fp_src==NULL || fp_dst==NULL)
{
perror("Error open yuv files:");
return -1;
}
x265_param_default(¶m);
param.bRepeatHeaders = 1;//write sps,pps before keyframe
param.internalCsp = csp;
param.sourceWidth = width;
param.sourceHeight = height;
param.fpsNum = 25; // 帧率
param.fpsDenom = 1; // 帧率
handle = x265_encoder_open(¶m);
if(handle == NULL)
{
printf("x265_encoder_open err\n");
goto out;
}
pic_in = x265_picture_alloc();
if (pic_in == NULL)
{
goto out;
}
x265_picture_init(¶m, pic_in);
// Y分量大小
luma_size = param.sourceWidth * param.sourceHeight;
// 分量一帧YUV的空间
switch (csp)
{
case X265_CSP_I444:
buff = (char *)malloc(luma_size*3);
pic_in->planes[0] = buff;
pic_in->planes[1] = buff + luma_size;
pic_in->planes[2] = buff + luma_size*2;
pic_in->stride[0] = width;
pic_in->stride[1] = width;
pic_in->stride[2] = width;
break;
case X265_CSP_I420:
buff = (char *)malloc(luma_size*3/2);
pic_in->planes[0] = buff;
pic_in->planes[1] = buff + luma_size;
pic_in->planes[2] = buff + luma_size*5/4;
pic_in->stride[0] = width;
pic_in->stride[1] = width/2;
pic_in->stride[2] = width/2;
break;
default:
printf("Colorspace Not Support.\n");
goto out;
}
// 计算总帧数
fseek(fp_src, 0, SEEK_END);
switch(csp)
{
case X265_CSP_I444:
i_frame = ftell(fp_src) / (luma_size*3);
chroma_size = luma_size;
break;
case X265_CSP_I420:
i_frame = ftell(fp_src) / (luma_size*3/2);
chroma_size = luma_size / 4;
break;
default:
printf("Colorspace Not Support.\n");
return -1;
}
fseek(fp_src,0,SEEK_SET);
printf("framecnt: %d, y: %d u: %d\n", i_frame, luma_size, chroma_size);
for(int i=0; i < i_frame; i++)
{
switch(csp)
{
case X265_CSP_I444:
case X265_CSP_I420:
if (fread(pic_in->planes[0], 1, luma_size, fp_src) != luma_size)
break;
if (fread(pic_in->planes[1], 1, chroma_size, fp_src) != chroma_size)
break;
if (fread(pic_in->planes[2], 1, chroma_size, fp_src) != chroma_size)
break;
break;
default:
printf("Colorspace Not Support.\n");
goto out;
}
ret = x265_encoder_encode(handle, &nal, &i_nal, pic_in, NULL);
printf("encode frame: %5d framesize: %d nal: %d\n", i+1, ret, i_nal);
if (ret < 0)
{
printf("Error encode frame: %d.\n", i+1);
goto out;
}
for(uint32_t j = 0; j < i_nal; j++)
{
fwrite(nal[j].payload, 1, nal[j].sizeBytes, fp_dst);
}
}
// Flush Decoder
while((ret = x265_encoder_encode(handle, &nal, &i_nal, NULL, NULL)))
{
static int cnt = 1;
printf("flush frame: %d\n", cnt++);
for(uint32_t j=0; j < i_nal; j++)
{
fwrite(nal[j].payload, 1, nal[j].sizeBytes, fp_dst);
}
}
out:
x265_encoder_close(handle);
x265_picture_free(pic_in);
if (buff)
free(buff);
fclose(fp_src);
fclose(fp_dst);
return 0;
}
使用方法:
x265_encode("../src/suzie_qcif_176x144_yuv420p.yuv", 176, 144, 1, "test.h265");
Makefile见上一文章所述。
李迟 2015.9.14 中午