最简单的视频编码器:基于libx265(编码YUV为H.265)

=====================================================

最简单的视频编码器系列文章列表:

最简单的视频编码器:编译

最简单的视频编码器:基于libx264(编码YUV为H.264)

最简单的视频编码器:基于libx265(编码YUV为H.265)

最简单的视频编码器:libvpx(编码YUV为VP8)

=====================================================

本文记录一个最简单的基于libx265的H.265(HEVC)视频编码器。此前记录的编码器是通过FFmpeg调用libx265完成编码的,例如:

《最简单的基于FFmpeg的视频编码器-更新版(YUV编码为HEVC(H.265))》

相比与上文中的编码器,本文记录的编码器属于“轻量级”的编码器。因为它不再包含FFmpeg的代码,直接调用libx265完成编码。因此项目的体积非常小巧。该编码器可以将输入的YUV数据编码为H.265码流文件。

流程图

调用libx265进行视频编码的流程图如下所示。

 

从流程图中可以看出x265的API和x264的API十分相似。它们在用法上只有微小的不同。
流程图中主要的函数如下所示。
x265_param_alloc():为参数集结构体x265_param分配内存。
x265_param_default():设置参数集结构体x265_param的缺省值。
x265_picture_alloc():为图像结构体x265_picture分配内存。
x265_picture_init():设置图像结构体x265_picture的缺省值。
x265_encoder_open():打开编码器。
x265_encoder_encode():编码一帧图像。
x265_encoder_close():关闭编码器。
x265_picture_free():释放x265_picture_alloc()申请的资源。
x265_param_free():释放x265_param_alloc()申请的资源。

存储数据的结构体如下所示。
x265_picture:存储压缩编码前的像素数据。
x265_nal:存储压缩编码后的码流数据。

此外流程图中还包括一个“flush_encoder”模块,该模块使用的函数和编码模块是一样的。唯一的不同在于不再输入视频像素数据。它的作用是输出编码器中剩余的码流数据。

源代码

[cpp]  view plain copy
  1. /** 
  2.  * 最简单的基于X265的视频编码器 
  3.  * Simplest X265 Encoder 
  4.  * 
  5.  * 雷霄骅 Lei Xiaohua 
  6.  * leixiaohua1020@126.com 
  7.  * 中国传媒大学/数字电视技术 
  8.  * Communication University of China / Digital TV Technology 
  9.  * http://blog.csdn.net/leixiaohua1020 
  10.  * 
  11.  * 本程序可以YUV格式的像素数据编码为H.265码流,是最简单的 
  12.  * 基于libx265的视频编码器 
  13.  * 
  14.  * This software encode YUV data to H.265 bitstream. 
  15.  * It's the simplest encoder example based on libx265. 
  16.  */  
  17. #include <stdio.h>  
  18. #include <stdlib.h>  
  19.   
  20. #if defined ( __cplusplus)  
  21. extern "C"  
  22. {  
  23. #include "x265.h"  
  24. };  
  25. #else  
  26. #include "x265.h"  
  27. #endif  
  28.   
  29. int main(int argc, char** argv){  
  30.     int i,j;  
  31.     FILE *fp_src=NULL;  
  32.     FILE *fp_dst=NULL;  
  33.     int y_size;  
  34.     int buff_size;  
  35.     char *buff=NULL;  
  36.     int ret;  
  37.     x265_nal *pNals=NULL;  
  38.     uint32_t iNal=0;  
  39.   
  40.     x265_param* pParam=NULL;  
  41.     x265_encoder* pHandle=NULL;  
  42.     x265_picture *pPic_in=NULL;  
  43.   
  44.     //Encode 50 frame  
  45.     //if set 0, encode all frame  
  46.     int frame_num=50;  
  47.     int csp=X265_CSP_I420;  
  48.     int width=640,height=360;  
  49.   
  50.     fp_src=fopen("../cuc_ieschool_640x360_yuv420p.yuv","rb");  
  51.     //fp_src=fopen("../cuc_ieschool_640x360_yuv444p.yuv","rb");  
  52.   
  53.     fp_dst=fopen("cuc_ieschool.h265","wb");  
  54.     //Check  
  55.     if(fp_src==NULL||fp_dst==NULL){  
  56.         return -1;  
  57.     }  
  58.   
  59.     pParam=x265_param_alloc();  
  60.     x265_param_default(pParam);  
  61.     pParam->bRepeatHeaders=1;//write sps,pps before keyframe  
  62.     pParam->internalCsp=csp;  
  63.     pParam->sourceWidth=width;  
  64.     pParam->sourceHeight=height;  
  65.     pParam->fpsNum=25;  
  66.     pParam->fpsDenom=1;  
  67.     //Init  
  68.     pHandle=x265_encoder_open(pParam);  
  69.     if(pHandle==NULL){  
  70.         printf("x265_encoder_open err\n");  
  71.         return 0;  
  72.     }  
  73.     y_size = pParam->sourceWidth * pParam->sourceHeight;  
  74.   
  75.     pPic_in = x265_picture_alloc();  
  76.     x265_picture_init(pParam,pPic_in);  
  77.     switch(csp){  
  78.     case X265_CSP_I444:{  
  79.         buff=(char *)malloc(y_size*3);  
  80.         pPic_in->planes[0]=buff;  
  81.         pPic_in->planes[1]=buff+y_size;  
  82.         pPic_in->planes[2]=buff+y_size*2;  
  83.         pPic_in->stride[0]=width;  
  84.         pPic_in->stride[1]=width;  
  85.         pPic_in->stride[2]=width;  
  86.         break;  
  87.                        }  
  88.     case X265_CSP_I420:{  
  89.         buff=(char *)malloc(y_size*3/2);  
  90.         pPic_in->planes[0]=buff;  
  91.         pPic_in->planes[1]=buff+y_size;  
  92.         pPic_in->planes[2]=buff+y_size*5/4;  
  93.         pPic_in->stride[0]=width;  
  94.         pPic_in->stride[1]=width/2;  
  95.         pPic_in->stride[2]=width/2;  
  96.         break;  
  97.                        }  
  98.     default:{  
  99.         printf("Colorspace Not Support.\n");  
  100.         return -1;  
  101.             }  
  102.     }  
  103.       
  104.     //detect frame number  
  105.     if(frame_num==0){  
  106.         fseek(fp_src,0,SEEK_END);  
  107.         switch(csp){  
  108.         case X265_CSP_I444:frame_num=ftell(fp_src)/(y_size*3);break;  
  109.         case X265_CSP_I420:frame_num=ftell(fp_src)/(y_size*3/2);break;  
  110.         default:printf("Colorspace Not Support.\n");return -1;  
  111.         }  
  112.         fseek(fp_src,0,SEEK_SET);  
  113.     }  
  114.   
  115.     //Loop to Encode  
  116.     for( i=0;i<frame_num;i++){  
  117.         switch(csp){  
  118.         case X265_CSP_I444:{  
  119.             fread(pPic_in->planes[0],1,y_size,fp_src);       //Y  
  120.             fread(pPic_in->planes[1],1,y_size,fp_src);       //U  
  121.             fread(pPic_in->planes[2],1,y_size,fp_src);       //V  
  122.             break;}  
  123.         case X265_CSP_I420:{  
  124.             fread(pPic_in->planes[0],1,y_size,fp_src);       //Y  
  125.             fread(pPic_in->planes[1],1,y_size/4,fp_src); //U  
  126.             fread(pPic_in->planes[2],1,y_size/4,fp_src); //V  
  127.             break;}  
  128.         default:{  
  129.             printf("Colorspace Not Support.\n");  
  130.             return -1;}  
  131.         }  
  132.   
  133.         ret=x265_encoder_encode(pHandle,&pNals,&iNal,pPic_in,NULL);   
  134.         printf("Succeed encode %5d frames\n",i);  
  135.   
  136.         for(j=0;j<iNal;j++){  
  137.             fwrite(pNals[j].payload,1,pNals[j].sizeBytes,fp_dst);  
  138.         }     
  139.     }  
  140.     //Flush Decoder  
  141.     while(1){  
  142.         ret=x265_encoder_encode(pHandle,&pNals,&iNal,NULL,NULL);  
  143.         if(ret==0){  
  144.             break;  
  145.         }  
  146.         printf("Flush 1 frame.\n");  
  147.   
  148.         for(j=0;j<iNal;j++){  
  149.             fwrite(pNals[j].payload,1,pNals[j].sizeBytes,fp_dst);  
  150.         }  
  151.     }  
  152.       
  153.     x265_encoder_close(pHandle);  
  154.     x265_picture_free(pPic_in);  
  155.     x265_param_free(pParam);  
  156.     free(buff);  
  157.     fclose(fp_src);  
  158.     fclose(fp_dst);  
  159.       
  160.     return 0;  
  161. }  

运行结果

程序的输入为一个YUV文件(已经测试过YUV444P和YUV420P两种格式)。


输出为H.265码流文件。


H.265码流文件的信息如下所示。


下载


Simplest Encoder

项目主页

SourceForge:https://sourceforge.net/projects/simplestencoder/

Github:https://github.com/leixiaohua1020/simplest_encoder

开源中国:http://git.oschina.net/leixiaohua1020/simplest_encoder


CDSN下载地址:http://download.csdn.net/detail/leixiaohua1020/8284105


该解决方案包含了几个常见的编码器的使用示例:
simplest_vpx_encoder:最简单的基于libvpx的视频编码器
simplest_x264_encoder:最简单的基于libx264的视频编码器
simplest_x265_encoder:最简单的基于libx265的视频编码器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: FFmpeg是一款流媒体处理的工具,支持多种视频编码格式,其中也包括YUV编码。H.265是一种高效的视频编码格式,可以将视频文件的大小压缩至原来的一半。 要将YUV编码的视频文件转换为H.265编码,需要进行以下步骤: 1. 通过FFmpeg获取原始视频的YUV数据。 2. 将YUV数据进行处理,将其转换为H.265编码格式。此处需要使用x265编码,以实现高质量的视频编码。 3. 将处理后的H.265编码数据转化为保存为视频文件。 在使用FFmpeg进行YUV编码为H.265的操作时,需要注意以下几点: 1. YUV数据的格式应该符合编码的要求,否则将无法进行编码。 2. 编码参数的选择对于编码质量和压缩率都有很大影响,需要注意对应的参数设置。 3. H.265编码是比较耗时的操作,需要足够的计算机性能支持。 通过上述步骤,我们可以将YUV格式的视频文件转换为高效的H.265格式,实现更好的视频质量和更小的视频文件大小。 ### 回答2: FFmpeg是一个跨平台的音视频处理库,其中也包括了对YUV数据的处理和编码功能。而H.265是一种高效的视频编码标准,能够提供更好的视频质量和更小的文件大小。因此,将YUV数据编码为H.265对于提高视频编码的效率和质量非常重要。 在FFmpeg中,可以使用x265编码来将YUV数据编码为H.265。首先,需要将YUV数据加载到FFmpeg中,并设置相应的编码参数。然后,使用x265编码YUV数据进行压缩编码,并输出为H.265视频文件格式。 具体步骤如下: 1. 使用FFmpeg加载YUV数据,可以通过命令行输入以下命令: ffmpeg -s:v widthxheight -pix_fmt yuv420p -i input.yuv 其中,width和height分别表示YUV数据的宽度和高度,input.yuvYUV数据的文件名。 2. 设置编码参数,可以通过命令行指定编码的参数,例如: ffmpeg -c:v libx265 -preset medium -x265-params keyint=60 -b:v 2M output.mp4 其中,-c:v表示指定使用x265编码,-preset medium表示设置为中等压缩质量,-x265-params keyint=60表示设置关键帧间隔为60,-b:v 2M表示设置输出视频的比特率为2M,output.mp4表示输出为H.265视频文件。 3. 进行YUV编码,可以使用以下命令实现: ffmpeg -i input.yuv -c:v libx265 -preset medium -x265-params keyint=60 -b:v 2M output.mp4 其中,-i input.yuv表示输入YUV数据文件,-c:v libx265表示指定使用x265编码进行编码,后续参数同上。 通过以上步骤,就可以将YUV数据编码为H.265格式的视频文件,从而利用H.265标准的高效性能优势来提高视频编码的效率和质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值