最簡單的視頻編碼器:基於libx265(編碼YUV爲H.265)

http://blog.csdn.net/leixiaohua1020/article/details/42079101git

 

目錄(?)[+]ide

 

 

=====================================================函數

最簡單的視頻編碼器系列文章列表:oop

最簡單的視頻編碼器:編譯

 

最簡單的視頻編碼器:基於libx264(編碼YUV爲H.264)post

最簡單的視頻編碼器:基於libx265(編碼YUV爲H.265)測試

最簡單的視頻編碼器:libvpx(編碼YUV爲VP8)ui

=====================================================編碼

本文記錄一個最簡單的基於libx265的H.265(HEVC)視頻編碼器。此前記錄的編碼器是經過FFmpeg調用libx265完成編碼的,例如:spa

《最簡單的基於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的視頻編碼器
相關文章
相關標籤/搜索