海思媒體(mmp)處理平臺架構
海思媒體處理平臺的主要內部處理流程如圖 1-2 所示,主要分爲視頻輸入(VI)、視頻處理(VPSS)、視頻編碼(VENC)、視頻解碼(VDEC)、視頻輸出(VO)、視頻偵測分析(VDA)、音頻輸入(AI)、音頻輸出(AO)、音頻編碼(AENC)、音頻解碼(ADEC)、區域管理(REGION)等模塊。主要的處理流程介紹如下:
VI 模塊捕獲視頻圖像,可對其做剪切、縮放等處理,並輸出多路不同分辨率的圖像數據。解碼模塊對編碼後的視頻碼流進行解碼,並將解析後的圖像數據送 VPSS 進行圖像處理或直接送 VO 顯示。可對 H264/MPEG4/MPEG2 格式的視頻碼流進行解碼。
VPSS 模塊接收 VI 和解碼模塊發送過來的圖像,可對圖像進行去噪、圖像增強、銳化等處理,並實現同源輸出多路不同分辨率的圖像數據用於編碼、預覽或抓拍。
編碼模塊接收 VI 捕獲並經 VPSS 處理後輸出的圖像數據,可疊加用戶通過 Region模塊設置的 OSD 圖像,然後按不同協議進行編碼並輸出相應碼流。
VDA 模塊接收 VI 的輸出圖像,並進行移動偵測和遮擋偵測,最後輸出偵測分析結果。
VO 模塊接收 VPSS 處理後的輸出圖像,可進行播放控制等處理,最後按用戶配置的輸出協議輸出給外圍視頻設備。
AI 模塊捕獲音頻數據,然後 AENC 模塊支持按多種音頻協議對其進行編碼,最後輸出音頻碼流。
用戶從網絡或外圍存儲設備獲取的音頻碼流可直接送給 ADEC 模塊, ADEC 支持解碼多種不同的音頻格式碼流,解碼後數據送給 AO 模塊即可播放聲音。
下面的代碼我把不會用到的代碼刪除了,這樣更簡潔,爲了簡介,下面我只做一路輸出,只選擇APTINA_AR0130_DC_720P_30FPS爲視頻輸出格式
int main(int argc, char *argv[])
{
HI_S32 s32Ret;
signal(SIGINT, SAMPLE_VENC_HandleSig);//ctrl+c,delete
signal(SIGTERM, SAMPLE_VENC_HandleSig);//ctrl+\
/* H.264@1080p@30fps+H.265@1080p@30fps+H.264@D1@30fps */
s32Ret = SAMPLE_VENC_1080P_CLASSIC();
if (HI_SUCCESS == s32Ret)
printf("program exit normally!\n");
else
printf("program exit abnormally!\n");
exit(s32Ret);
}
SAMPLE_VENC_HandleSig:主要做系統的回收,ISP線程的退出,ISP的停止
SAMPLE_VENC_1080P_CLASSIC:H.264@1080p@30fps+H.265@1080p@30fps+H.264@D1@30fps這幾種情況的處理
由於海思的應用程序啓動 MPP 業務前,必須完成 MPP 系統初始化工作。同理,應用程序退出MPP 業務後,也要完成 MPP 系統去初始化工作,釋放資源。
初始化工作主要爲:
各個模塊之間的綁定
可以參考:https://blog.csdn.net/qq_40732350/article/details/87970605
在H264_Venc()函數裏先去初始化MPI系統,然後根據攝像頭設置參數。我這裏是AR030攝像頭,其拍攝圖片大小爲720P,編碼爲H264,爲了簡單隻輸出一路。在初始化MPI系統時要計算視頻緩存池VB_CONF_S的大小,然後填充VB_CONF_S結構體。填充完VB_CONF_S結構體後再用HI_MPI_VB_SetConf設置,最後初始化視頻視頻緩存池HI_MPI_VB_Init。這裏注意的是基本上每個函數調用後都會判斷返回值並作出錯出理,後面很多函數也是這樣處理的,這樣利於程序排錯
第一步:初始化視頻緩衝池和系統MPP初始化
//爲了簡單點,編碼類型就選擇PT_H264,圖片大小就選擇PIC_HD720,通道也只用1路s32ChnNum=1
PAYLOAD_TYPE_E enPayLoad=PT_H264;//264編碼
PIC_SIZE_E enSize=PIC_HD720;//攝像頭拍攝圖片的大小,這裏只用720P
HI_S32 s32ChnNum=1;//支持一路攝像
HI_S32 s32Ret=HI_FAILURE;
/******************************************
mpp system init.
******************************************/
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
VB_CONF_S stVbConf;//緩存池參數結構體
HI_U32 u32BlkSize;//一張圖片佔多少字節
memset(&stVbConf,0,sizeof(VB_CONF_S));
//根據制式,圖片大小,圖片格式及對齊方式確定圖片緩存大小
//這裏用NTSC,720P,YUV420,64字節對齊
u32BlkSize=SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,enSize, PIXEL_FORMAT_YUV_SEMIPLANAR_420, \
SAMPLE_SYS_ALIGN_WIDTH);
printf("u32BlkSize=%d\n",u32BlkSize);
stVbConf.u32MaxPoolCnt = 128;//用默認值,3518默認是128
stVbConf.astCommPool[0].u32BlkSize = u32BlkSize;//(寬+壓縮頭 stride) * 高 * 1.5 參考MPP手冊94
stVbConf.astCommPool[0].u32BlkCnt = g_u32BlkCnt; //4個緩衝塊
//設置緩衝池
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
s32Ret = HI_MPI_VB_SetConf(&stVbConf);//設置 MPP 視頻緩存池屬性
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VB_SetConf failed!\n");
return HI_FAILURE;
}
s32Ret = HI_MPI_VB_Init();//初始化 MPP 視頻緩存池
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VB_Init failed!\n");
return HI_FAILURE;
}
//設置系統屬性
MPP_SYS_CONF_S stSysConf = {0};
HI_S32 s32Ret = HI_FAILURE;
stSysConf.u32AlignWidth = SAMPLE_SYS_ALIGN_WIDTH; //64
s32Ret = HI_MPI_SYS_SetConf(&stSysConf);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_SetConf failed\n");
return HI_FAILURE;
}
s32Ret = HI_MPI_SYS_Init();
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_Init failed!\n");
return HI_FAILURE;
}