当前位置: 移动技术网 > 移动技术>移动开发>IOS > 借助libx265库实现一个简单视频编码器

借助libx265库实现一个简单视频编码器

2020年07月13日  | 移动技术网移动技术  | 我要评论

1.VS新建工程

win10+VS2013,新建一个工程,x265_self;
右键源文件,添加新建项,x265_self.cpp;
右键头文件/外部依赖项,添加x265.h, x265_config.h(文末附)。

2. 编写main函数

只是简单实现一个编码过程,主要包括以下几个过程:
x265_param结构体:存储编码命令行参数;
x265_encoder结构体:编码器相关参数;
x265_picture结构体:存储读取的每一帧,用于编码;

x265_param_alloc():定义参数集并为参数集分配内存;
x265_param_default(pParam):设置默认参数;
x265_encoder_open(pParam):打开编码器,并依据pParam进行配置初始化;
x265_picture_alloc():为图像结构体x265_picture分配内存
x265_picture_init(pParam, pPic_in):依据命令行参数,进行图像结构体初始化
x265_encoder_encode():编码核心函数,将pPic_in内存的图像转化为二进制码流;

/Flush Decoder/部分,使用的函数和编码模块是一样的。唯一的不同在于不再输入视频像素数据。它的作用是输出编码器中剩余的码流数据。

int main(int argc, char** argv){   //argc代表命令行给main的参数数量,
                                //argv存各参数地址,每一个元素指向一个参数
 int i, j;
 FILE *fp_src = NULL;
 FILE *fp_dst = NULL;
 char* buff = NULL;
 x265_param* pParam = NULL;
 x265_encoder* pHandle = NULL;
 x265_picture* pPic_in = NULL;
 int ret = 0;
 int y_size = 0;
 x265_nal *pNals = NULL;
 uint32_t iNal = 0;

 //encode 50 frames
 int frame_num = 50;
 int width = 640, height = 360;
 int csp = X265_CSP_I420;
 
 fp_src = fopen("../cuc_ieschool_640x360_yuv420p.yuv","rb");
 fp_dst = fopen("../cuc_ieschool.h265","wb");

 if (fp_src == NULL || fp_dst == NULL)
  return -1;

 //各编码参数变量的定义、初始化
 pParam = x265_param_alloc(); //定义、为参数集分配内存
 x265_param_default(pParam);
 //除默认配置外,以下参数自定义
 pParam->sourceWidth = width;
 pParam->sourceHeight = height;
 pParam->fpsNum = 25;
 pParam->fpsDenom = 1;
 pParam->internalCsp = csp;

 //打开编码器,并依据pParam进行配置初始化
 pHandle = x265_encoder_open(pParam);
 if (pHandle == NULL){
  printf("x265_encoder_open() err\n");
  return 0;
 }
 y_size = pParam->sourceHeight * pParam->sourceWidth;

 //为图像结构体x265_picture分配内存 
 pPic_in = x265_picture_alloc(); 
 x265_picture_init(pParam, pPic_in);

 switch (csp){
 case X265_CSP_I420:{
     buff = (char*)malloc(y_size*3/2);  //申请内存够一帧420图像的
  pPic_in->planes[0] = buff;         //记录各通道首地址
  pPic_in->planes[1] = buff+y_size;
  pPic_in->planes[2] = buff+y_size*5/4;
  pPic_in->stride[0] = width;        //记录各通道步长
  pPic_in->stride[1] = width / 2;
  pPic_in->stride[2] = width / 2;
  break;
 }
 default:{
    printf("Colorspace not support.\n");
    return -1;
 }
 }
 //计算总帧数
 if (frame_num == 0){
  fseek(fp_src, 0, SEEK_END);//将读写位置移动到文件尾
  // ftell 用于得到文件位置指针当前位置相对于文件首的偏移字节数
  switch (csp){
  case X265_CSP_I420:frame_num = ftell(fp_src) / (y_size * 3 / 2); break;
  default:printf("Colorspace Not Support.\n"); 
   return -1;
  }
  fseek(fp_src, 0, SEEK_SET); //将读写位置移回到文件头
 }

 //循环每帧编码
 for ( i = 0; i < frame_num; i++){
  switch (csp){
  case X265_CSP_I420:{
   //从fp_src中读取,y_size次,每次1个字节,存到pPic_in
   fread(pPic_in->planes[0], 1, y_size, fp_src);       //Y 
   fread(pPic_in->planes[1], 1, y_size / 4, fp_src); //U
   fread(pPic_in->planes[2], 1, y_size / 4, fp_src); //V
   break;
  }
  default:{
     printf("Colorspace Not Support.\n");
     return -1; }
  }
  ret = x265_encoder_encode(pHandle, &pNals, &iNal, pPic_in, NULL);
  printf("Succeed encode %5d frames\n", i);
  
  //fwrite以二进制写入文件,从pNals中,取pNals[j].sizeBytes个元素
  //每次1字节,写入fp_dst
  for ( j = 0; j<iNal; j++){
   fwrite(pNals[j].payload, 1, pNals[j].sizeBytes, fp_dst);
  }
 }

 /*Flush Decoder,使用的函数和编码模块是一样的。
   唯一的不同在于不再输入视频像素数据。
   它的作用是输出编码器中剩余的码流数据。*/
 while (1){
  ret = x265_encoder_encode(pHandle, &pNals, &iNal, NULL, NULL);
  if (ret == 0){
   break;
  }
  printf("Flush 1 frame.\n");
  for ( j = 0; j<iNal; j++){
   fwrite(pNals[j].payload, 1, pNals[j].sizeBytes, fp_dst);
  }
 }
 x265_encoder_close(pHandle);
 x265_picture_free(pPic_in);
 x265_param_free(pParam);
 free(buff);
 fclose(fp_src);
 fclose(fp_dst);

 return 0;
}

3.添加库配置

将libx265.lib、libx265.dll复制到cpp所在文件夹,右键工程->属性,
VC++目录->库目录,添加libx265.lib所在目录;
链接器->附加库目录,添加libx265.lib所在目录;
链接器->附加依赖项,添加libx265.lib;
c/c+±>预处理器定义,添加_CRT_SECURE_NO_WARNINGS;(为了消除VS对fopen等函数的报错)

生成解决方案,即可得到所需exe编码器;
调试/运行,即可完成编码得到压缩后的.h265文件;
PS:我们这里在main函数里直接定义了输入输出文件,所以不需要命令行,直接运行即可完成编码。

本文参考雷神的“最简单的视频编码器:最简单的视频编码器:基于libx265(编码YUV为H.265)”,并增加了一些配置说明,致敬雷神。

工程文件:
CSDN:https://download.csdn.net/download/baozhakaiv/12598720

本文地址:https://blog.csdn.net/baozhakaiv/article/details/107261037

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网