目录
一、前言
二、x265介绍
三、x265主要编码接口介绍
1、int x265_param_default_preset(x265_param *, const char *preset, const char *tune)
2、int x265_param_apply_profile(x265_param *, const char *profile);
3、x265_encoder* x265_encoder_open(x265_param *)
4、void x265_encoder_close(x265_encoder *)
5、int x265_encoder_headers(x265_encoder *, x265_nal **pp_nal, uint32_t *pi_nal)
6、x265_picture *x265_picture_alloc(void);
7、void x265_picture_free(x265_picture *);
8、void x265_picture_init(x265_param *param, x265_picture *pic);
9、int x265_encoder_encode(x265_encoder *encoder, x265_nal **pp_nal, uint32_t *pi_nal, x265_picture *pic_in, x265_picture *pic_out);
四、x265编码yuv的代码示例
1、编码器参数初始化
2、打开编码器
3、关闭编码器
4、编码输入图像缓存申请
5、编码输入图像缓存释放
6、编码一帧YUV
7、编码器关闭
8、编码参数资源释放
9、输入图像资源释放
五、x265编码软件框图
《libx265编码摄像头数据为H265代码实现》链接:
https://edu.csdn.net/learn/38258/606134?spm=1003.2001.3001.4157
随着高清视频的发展,4k、8K分辨率的视频越来越多,但是4k、8k等超大分辨数据也是非常大,所以就需要一个压缩效率更高的视频压缩编码器,于是2013年推出了新一代压缩编码标准H265(HEVC)。x265软件编码器就是一个开源的H265编码器。
和x264类似,x265不仅提供了一个命令行工具进行编码,还提供了一组丰富的接口(API)可以被调用来编码h265视频。x265开源软件下载路径为:https://github.com/videolan/x265.git
该函数是对x265编码器配置默认参数,并根据第二第三个参数进行场景化"一键"配置。该函数调用x265_param_default的接口进行默认参数配置的;如下图是x265_param_default函数里面部分参数配置代码。
x265_param_default_preset函数会根据第二个参数preset配置编码器参数来配置画质和速度的一个取舍。preset的取值如下,medium是默认的一个参数配置;medium之前的是编码速度快、画质会降低的的场景,如ultrafast的编码速度最快,画质可能最差的;medium之后的是编码速度慢、画质会提升的的场景,如veryslow的编码速度是非常慢,画质也会明显的提示。
const x265_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo", 0 };
x265_param_default_preset函数第三个参数tune是根据不同场景下配置不同的参数,tune的参数如下;zerolatency通常在x265实时场景中使用,表示低延迟的场景配置。
const x265_tune_names[] = { "psnr", "ssim", "grain", "zerolatency", "fastdecode", "animation", 0 };
该函数用于配置H265编码档次,入参profile支持的档次如下;在H265视频码流结构分析
一文中介绍了H265编码器的档次。
static const char * const x265_profile_names[] = {
/* HEVC v1 */
"main", "main10", "mainstillpicture", /* alias */ "msp",
/* HEVC v2 (Range Extensions) */
"main-intra", "main10-intra",
"main444-8", "main444-intra", "main444-stillpicture",
"main422-10", "main422-10-intra",
"main444-10", "main444-10-intra",
"main12", "main12-intra",
"main422-12", "main422-12-intra",
"main444-12", "main444-12-intra",
"main444-16-intra", "main444-16-stillpicture", /* Not Supported! */
0
};
该函数用于打开一个编码器。根据x265_param 参数创建一个h265的编码器并返回编码器的句柄。
该函数用于关闭编码器。输入参数x265_encoder 是x265_encoder_open函数返回的句柄。
在开始编码yuv之前可以通过该函数用于获取该编码器中输出码流的nal单元部信息数据,包含SPS、PPS等信息。
该函数用于申请一个x265_picture 类型的变量。x265_picture的定义如下,包含了当前图像的pts、数据地址planes[3]、数据地址跨距stride[3]、图像像素位深bitDepth等。
typedef struct x265_picture
{
/* presentation time stamp: user-specified, returned on output */
int64_t pts;
/* display time stamp: ignored on input, copied from reordered pts. Returned
* on output */
int64_t dts;
/* force quantizer for != X265_QP_AUTO */
/* The value provided on input is returned with the same picture (POC) on
* output */
void* userData;
/* Must be specified on input pictures, the number of planes is determined
* by the colorSpace value */
void* planes[3];
/* Stride is the number of bytes between row starts */
int stride[3];
int bitDepth;
/* Must be specified on input pictures: X265_TYPE_AUTO or other.
* x265_picture_init() sets this to auto, returned on output */
int sliceType;
/* Ignored on input, set to picture count, returned on output */
int poc;
/* Must be specified on input pictures: X265_CSP_I420 or other. It must
* match the internal color space of the encoder. x265_picture_init() will
* initialize this value to the internal color space */
int colorSpace;
/* Force the slice base QP for this picture within the encoder. Set to 0
* to allow the encoder to determine base QP */
int forceqp;
x265_analysis_data analysisData;
float *quantOffsets;
/* Frame level statistics */
x265_frame_stats frameData;
/* User defined SEI */
x265_sei userSEI;
/* Ratecontrol statistics for collecting the ratecontrol information.
* It is not used for collecting the last pass ratecontrol data in
* multi pass ratecontrol mode. */
void* rcData;
uint64_t framesize;
int height;
// pts is reordered in the order of encoding.
int64_t reorderedPts;
//Dolby Vision RPU metadata
x265_dolby_vision_rpu rpu;
int fieldNum;
} x265_picture;
该函数用于释放x265_picture_alloc申请的变量地址。
该函数根据编码器参数x265_param 来初始化x265_picture。该函数的定义如下,主要是对x265_picture里面的变量赋值,如位深、图像颜色空间等。
该函数主要是对输入的图像YUV进行编码输出一个编码帧数据,也可以返回编码重建解码的YUV。encoder:编码器句柄。
pp_nal:存放SPS、PPS、ISlices、Psliec等nal单元信息的地址
pi_nal:nal单元头的个数,比如nal只有VPS、SPS、PPS则该值为3,如果还包含了ISlice该值为4.
pic_in:输入yuv帧数据,当该值为空的时候会刷新编码器缓冲区强制输出最后一帧编码数据。通常在编码结束关闭编码器前调用x265_encoder_encode函数并将pic_in设置NULL,来强制输出最后一帧确保编码器缓存为空。
pic_out :通常是编码过程中该帧编码后重建的yuv。
h265_enc_init函数申请编码参数资源并根据编码分辨率帧率设置编码参数,该套参数通常用于低延时场景,追求编码速度快。
static x265_param *h265_enc_init(int width,int height,int fps)
{
x265_param* pX265Param = x265_param_alloc();
x265_param_default_preset(pX265Param, "ultrafast", "zerolatency");
pX265Param->sourceWidth = width; //* width
pX265Param->sourceHeight = height; //* height
pX265Param->keyframeMax = 2 * fps;
pX265Param->rc.bitrate = 1024 * 512; //设置编码码率512kbps
pX265Param->fpsDenom = 1; //编码帧率
pX265Param->fpsNum = fps*2;
pX265Param->bRepeatHeaders = 1; //sps/pps等重复出现在I帧头部
pX265Param->bAnnexB = 1;
pX265Param->internalCsp = X265_CSP_I420;
x265_param_apply_profile(pX265Param, x265_profile_names[0]); //main
return pX265Param;
}
根据编码器配置参数调用x265编码器打开编码器返回句柄,
static x265_encoder* h265_enc_open(x265_param *pX265Param)
{
return x265_encoder_open(pX265Param);
}
传入编码器句柄来关闭已经打开的编码器。
void h265_enc_close(x265_encoder *encHandle)
{
x265_encoder_close(encHandle);
}
根据输入图像分辨率和图像格式申请输入图像的缓存。
static x265_picture* h265_enc_pic_alloc(x265_param *pH265Param)
{
x265_picture* pPic = x265_picture_alloc();
x265_picture_init(pH265Param,pPic);
uint8_t * buff = new uint8_t [pH265Param->sourceWidth * pH265Param->sourceHeight * 3 / 2];
pPic->planes[0] = buff;
pPic->planes[1] = buff + pH265Param->sourceWidth * pH265Param->sourceHeight;
pPic->planes[2] = buff + pH265Param->sourceWidth * pH265Param->sourceHeight + pH265Param->sourceWidth * pH265Param->sourceHeight / 4;
pPic->stride[0] = pH265Param->sourceWidth;
pPic->stride[1] = pH265Param->sourceWidth / 2;
pPic->stride[2] = pH265Param->sourceWidth / 2;
return pPic;
}
static void h265_enc_pic_free(x265_picture *pPic)
{
delete [] pPic->planes[0];
x265_picture_free(pPic);
}
输入YUV图像,编码后返回编码帧nal包的地址和包的个数。
static int h265_encoder(x265_encoder *pX265Handle, x265_picture* pPicIn,x265_nal**pNals,uint64_t *pEncPts)
{
x265_picture pic_out = {0};
uint32_t i_nal = 0,numEncoded = 0;
if(pPicIn) //编码一帧yuv
{
numEncoded = x265_encoder_encode(pX265Handle, pNals, &i_nal, pPicIn, &pic_out);
if(numEncoded < 0)
{
std::cout << " x265_encoder_encode error"<< std::endl;
return -1;
}
}
else //刷新编码缓存-通常是关闭编码器前的操作
{
numEncoded = x265_encoder_encode(pX265Handle, pNals, &i_nal, NULL, &pic_out);
if(numEncoded < 0)
{
std::cout << " x265_encoder_encode error"<< std::endl;
return -1;
}
}
if (pPicIn && (pic_out.pts != pPicIn->pts))
{
std::cout << "pic in pts:"<< pPicIn->pts<< " enc out pts:"<
void h265_enc_close(x265_encoder *encHandle)
{
x265_encoder_close(encHandle);
}
static void h265_enc_deinit(x265_param *pX265Param)
{
x265_param_free(pX265Param);
}
static void h265_enc_pic_free(x265_picture *pPic)
{
delete [] pPic->planes[0];
x265_picture_free(pPic);
}