4 海思Hi3518E實例代碼分析

海思媒體(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 系統去初始化工作,釋放資源。

初始化工作主要爲:

視頻緩存池的設置

各個模塊之間的綁定

設置VI/VPSS 離/在線模式

可以參考: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;
    }	

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章