1、簡介
VDEC用來解碼的,比如磁盤裏面有一個
VDA對視頻內容簡單的偵測
VPSS處理
VO是用於直接顯示的。
2、什麼是視頻緩衝池
(1)視頻的本質是多幀圖片,圖片的本質是RGB或rawRGB數據,要佔用一段連續內存
(2)視頻的裁剪、縮放、修正處理等各種操作,本質上就是對內存中的數據進行運算
(3)視頻緩存池(VB, video buffer)就是一段很大,又被合理劃分和管理的內存,用來做視頻數據的暫存和運算場地
(4)公共視頻緩存池的公共2字,可以理解爲全局變量,也就是各個模塊都能訪問的一段內存
(5)看似視頻緩存塊在各個模塊之間流轉,實際上並沒有內存複製,而是指針在傳遞
(6)視頻緩存池的內存由MPP來維護,我們在系統啓動時就把整個SDRAM分成了2部分:系統部分(由linux kernel來維護管理)和mpp部分(由mpp系統來維護管理)
(7)緩存池需要幾個,每個中包含幾個緩存塊,每個緩存塊多大,都是可以由用戶程序設置好參數,然後調用MPP的相應API來向MPP申請分配的。
海思3518e裏面有多個緩衝池,一個緩衝池裏面又有很多緩衝塊,大小相同地址相連,緩衝池的數量由內存大小決定(應該是自行劃定的吧,還未求證)這些都是由mpp維護的。
視頻處理流程大致如下,先從緩衝池取出一個緩衝塊,然後放入VI中,將一幀數據填充進bm,之後傳入vpss進行處理,然後將處理完是數據放入新的緩衝塊中,最後將剛剛使用過的Bmijk緩衝塊釋放回去。
3、相關的數據結構和API
(1)VB_CONF_S:用於參數設置的,設置緩衝池有幾個,緩衝塊的數量大小等。
typedef struct hiVB_CONF_S
{
HI_U32 u32MaxPoolCnt; //設置申請最多緩衝池的數量,範圍是0- 16/* max count of pools, (0,VB_MAX_POOLS] */
struct hiVB_CPOOL_S
{
HI_U32 u32BlkSize; //緩衝塊大小
HI_U32 u32BlkCnt; //緩衝塊數量
HI_CHAR acMmzName[MAX_MMZ_NAME_LEN]; //緩衝池的名字,用於調試階段可以看到名字
}astCommPool[VB_MAX_COMM_POOLS];//最大上限16個公共緩衝池
} VB_CONF_S;
(2)HI_MPI_VB_SetConf:API,用於將緩衝池信息設置到mpp系統中
(3)HI_MPI_VB_Init :API,執行設置緩衝池的操作。
【舉例】
HI_S32 s32ret;
VB_CONF_S stVbConf;
memset(&stVbConf,0,sizeof(VB_CONF_S));
stVbConf.u32MaxPoolCnt = 128; //設置緩衝池數量最大上限
stVbConf.astCommPool[0].u32BlkSize = 768*576*2; //設置第一個緩衝塊大小
stVbConf.astCommPool[0].u32BlkCnt = 20; //設置第一個緩衝塊數量
stVbConf.astCommPool[1].u32BlkSize = 384*288*2; //設置第二個緩衝塊大小
stVbConf.astCommPool[1].u32BlkCnt = 40; //設置第二個緩衝塊數量
s32ret = HI_MPI_VB_SetConf(&stVbConf); //將緩衝池信息設置到mpp系統中
if (HI_SUCCESS != s32ret)
{
printf("set vb err:0x%x\n", s32ret);
return s32ret;
}
s32ret = HI_MPI_VB_Init(); //初始化
if (HI_SUCCESS != s32ret)
{
printf("init vb err:0x%x\n", s32ret);
return s32ret;
}
SAMPLE_VENC_1080P_CLASSIC();函數主要工作流程。
程序主要是爲了錄像,指揮攝像頭採集圖像,然後將圖像編碼最後輸出碼流。
第一部分:初始化sys部分的變量,sys也就是mpp中的變量填充,列如VB結構體裏面的數據
第二部分:初始化mpp系統
第三部分:啓動VI部分(設備和通道),然後採集圖像(和攝像頭相關部分)
第四部分:啓動VPSS,然後將vi處理完的數據傳給vpss(使用bind函數將vi和vpss綁定在一起)
第五部分:啓動編碼,這部分由mpp內部完成,僅調用相關API即可。
第六部分:僅僅只是將流數據保存成文件。
3.1、第一部分詳解
首先清空VB_CONF_S結構體,爲了後續填充變量做準備。
然後調用SAMPLE_COMM_VI_GetSizeBySensor(PIC_SIZE_E *penSize)這個函數,傳入enSize數組,在這個函數裏面可以看到
SAMPLE_VI_MODE_E enMode = SENSOR_TYPE;,其中SENSOR_TYPE是在外部makefile中定義的,通過SENSOR_TYPE來確定enSize的內容,enSize是用於存放將來編碼之後傳輸出來的碼流。
s32ChnNum是設置輸出多少個碼流。
其中碼流輸出的圖像是一致的,但是分辨率大小是不一樣的,其中一路是主碼流,其他的則是從主碼流中裁剪縮放而來的。
一個緩衝池對應一個碼流。
SAMPLE_COMM_SYS_CalcPicVbBlkSize(VIDEO_NORM_E enNorm, PIC_SIZE_E enPicSize, PIXEL_FORMAT_E enPixFmt, HI_U32 u32AlignWidth)
這個函數是用於計算出一個緩衝塊需要多大空間。
VIDEO_NORM_E enNorm:傳入視頻格式,PAL制和NTSC制
PIC_SIZE_E enPicSize:圖像尺寸
PIXEL_FORMAT_E enPixFmt:像素格式
HI_U32 u32AlignWidth:需要對齊排布的大小
其中這個函數的塊大小=圖像大小(根據長寬高和像素格式求得)+頭信息。
u32VbSize = (CEILING_2_POWER(stSize.u32Width, u32AlignWidth) * \
CEILING_2_POWER(stSize.u32Height,u32AlignWidth) * \
((PIXEL_FORMAT_YUV_SEMIPLANAR_422 == enPixFmt)?2:1.5));
#define CEILING_2_POWER(x,a) ( ((x) + ((a) - 1) ) & ( ~((a) - 1) ) )//x往a上除,直到能被整除
第二部分
SAMPLE_COMM_SYS_Init(&stVbConf);
第三部分詳解
學習方法:繪製調用關係圖譜
(1)簡單瀏覽VI部分的調用層次,發現很複雜
(2)有些函數是sample寫的,有些是調用MPP的,數據結構也是2種都有
SAMPLE_xxx就是sample內部自己實現的
HI_MPI_xxx就是調用mmp(3)學習重點1:全局把控熟悉整個過程全景視圖。
(4)學習重點2:掌握細節數據結構元素含義,和遇到的概念。
(5)學習重點3:知道某些關鍵操作在哪裏定義,哪裏設置,將來需要改的時候能找到地方 。main
SAMPLE_VENC_1080P_CLASSIC
SAMPLE_COMM_VI_GetSizeBySensor(step1)
SAMPLE_COMM_SYS_CalcPicVbBlkSize
SAMPLE_COMM_SYS_GetPicSize
SAMPLE_COMM_SYS_Init(step2)
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
HI_MPI_VB_SetConf
HI_MPI_VB_Init
HI_MPI_SYS_SetConf
HI_MPI_SYS_Init
SAMPLE_COMM_VI_StartVi(step3)----------------------->
stViConfig.enViMode = SENSOR_TYPE; //sensor的類型
stViConfig.enRotate = ROTATE_NONE; //輸出圖像是否旋轉(0、90、180°等)
stViConfig.enNorm = VIDEO_ENCODING_MODE_AUTO;//圖像制式(PAL、NTSC)
stViConfig.enViChnSet = VI_CHN_SET_NORMAL; //圖像加工(鏡像、翻轉等)
stViConfig.enWDRMode = WDR_MODE_NONE; //WDR寬動態
IsSensorInput
SAMPLE_COMM_VI_StartIspAndVi
SAMPLE_COMM_VI_StartMIPI(1)//對sensor做必要的初始化
//mipi是sensor和主芯片hi3518e之間的一種接口
//常用的接口有MIPI、LVDS、DC
SAMPLE_COMM_VI_SetMipiAttr
fd = open("/dev/hi_mipi", O_RDWR);
ioctl(fd, HI_MIPI_SET_DEV_ATTR, pstcomboDevAttr)
SAMPLE_COMM_ISP_Init(2)//isp就是image signal process,圖像信號處理
//HI3518E內部的ISP硬件單元是隸屬於VI模塊的
sensor_register_callback //在sensor驅動中,在/component/isp/sensor
HI_MPI_AE_Register //註冊3A單元:自動曝光
HI_MPI_AWB_Register //註冊3A調試:自動白平衡
HI_MPI_AF_Register //註冊3A調試:自動對焦
HI_MPI_ISP_MemInit //分配內存單元
HI_MPI_ISP_SetWDRMode //寬動態
HI_MPI_ISP_SetPubAttr --------------------->
根據sensor的類型進行設置,填充stPubAttr結構體。
以AR0130爲例
stPubAttr.enBayer = BAYER_GRBG; //參考sensor手冊得知,像素排列順序
stPubAttr.f32FrameRate = 30; //幀率
stPubAttr.stWndRect.s32X = 0; //圖像區域的起始點X
stPubAttr.stWndRect.s32Y = 0; //圖像區域的起始點Y
stPubAttr.stWndRect.u32Width = 1280; //圖像長
stPubAttr.stWndRect.u32Height = 720; //圖像寬
HI_MPI_ISP_Init //初始化isp模塊
SAMPLE_COMM_ISP_Run(3)//創建線程運行isp
pthread_create(&gs_IspPid, &attr, (void* (*)(void*))Test_ISP_Run, NULL)
Test_ISP_Run
HI_MPI_ISP_Run
SAMPLE_COMM_VI_StartDev(4)
HI_MPI_VI_SetDevAttr //在step3中設置的參數,一路傳到這才被寫入硬件單元
HI_MPI_ISP_GetWDRMode //在上一步isp中設置了SetWDRMode,這一步獲取設置信息
HI_MPI_VI_SetWDRAttr
HI_MPI_VI_EnableDev //啓動硬件單元
SAMPLE_COMM_VI_StartChn(5) //設置主通道
HI_MPI_VI_SetChnAttr //
HI_MPI_VI_SetRotate
HI_MPI_VI_EnableChn
SAMPLE_COMM_SYS_GetPicSize(step4)//得到處理圖像的長和高
SAMPLE_COMM_VPSS_StartGroup //開啓Group
HI_MPI_VPSS_CreateGrp //先創建一個Group
HI_MPI_VPSS_GetNRParam//獲取NR的參數(降噪相關的)
HI_MPI_VPSS_SetNRParam//在寫入進去(如果要做降噪相關的處理就需要在這之前對參數進行修改)
HI_MPI_VPSS_StartGrp //最後再啓動
SAMPLE_COMM_VI_BindVpss //將Vpss創建出來的Group和Vi的channel綁定在一起。
HI_MPI_SYS_Bind //調用海思驅動。
SAMPLE_COMM_VPSS_EnableChn------------------------->
VpssChn = 0; //通道號
stVpssChnMode.enChnMode = VPSS_CHN_MODE_USER; //設置通道模式爲用戶模式
stVpssChnMode.bDouble = HI_FALSE; //現場幀率模式傳輸(不瞭解)
stVpssChnMode.enPixelFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
stVpssChnMode.u32Width = stSize.u32Width; //該通道輸出圖像的長
stVpssChnMode.u32Height = stSize.u32Height; //該通道輸出圖像的寬
stVpssChnMode.enCompressMode = COMPRESS_MODE_SEG;//內部壓縮圖像的模式
SAMPLE_COMM_VENC_Start(step5)//
SAMPLE_COMM_VENC_BindVpss//綁定Vpss和Venc的channel綁定在一起。
SAMPLE_COMM_VENC_StartGetStream(step6)//
SAMPLE_COMM_VENC_GetVencStreamProc
HI_MPI_VENC_GetChnAttr
SAMPLE_COMM_VENC_GetFilePostfix
HI_MPI_VENC_GetFd
HI_MPI_VENC_Query //返回狀態信息
HI_MPI_VENC_GetStream
SAMPLE_COMM_VENC_SaveStream//保存流文件
SAMPLE_COMM_VENC_SaveH264
HI_MPI_VENC_ReleaseStream //
SAMPLE_COMM_VENC_StopGetStream(step7)
4、vpss基礎知識
全稱:Video Process Sub-System
支持對一幅輸入圖像進行統一預處理,如去噪、去隔行等,然後再對各通道分別進行縮放、銳化等處理,最後輸出多種不同分辨率的圖像。概念:
GROUP:VPSS 對用戶提供組(GROUP)的概念,各 GROUP 分時複用 VPSS 硬件。每個 VPSS GROUP 包含多個通道,通道數目視方案實現有所不同。
CHANNEL:VPSS 組的通道。通道分爲 2 種:物理通道和擴展通道。VPSS 硬件提供多個物理通道,每個通道具有縮放、裁剪等功能。擴展通道具備縮放功能,它通過綁定物理通道,將物理通道輸出作爲自己的輸入,把圖像縮放成用戶設置的目標分辨率輸出。擴展通道藉助物理通道的輸出來進行處理。
FRC:幀率控制,分爲 2 種:group 幀率控制和 chn 幀率控制。例如可變幀率的錄製。
Crop:裁剪,分爲 3 種:group 的裁剪和物理通道的裁剪以及擴展通道的裁剪。
− Group 的裁剪,VPSS 對輸入圖像進行裁剪。− 物理通道的裁剪,VPSS 對各個物理通道的輸出圖像進行裁剪。
− 擴展通道的裁剪,VPSS 調用 VGS 對擴展通道的輸出圖像進行裁剪。
DEI:De-interlace,去隔行。將交錯的隔行視頻源還原成逐行視頻源。
NR:去噪。通過參數配置,把圖像中的高斯噪聲去除,使得圖像變得平滑,有助於降低編碼碼率。
Scale:縮放,對圖像進行縮小放大。
LDC:Lens Distortion Correction,鏡頭畸變校正,一些低端鏡頭容易產生圖像畸變,需要根據畸變程度對其圖像進行校正。
Cover:視頻遮擋區域,對 VPSS 的輸出圖像填充純色塊。
Overlay:視頻疊加區域,在 GROUP 上進行位圖的加載和背景色更新,支持 ARGB4444、ARGB1555、ARGB8888 三種格式的位圖。
Border:邊框,VPSS 在輸出圖像上加邊框。
備份節點:原始圖像的備份節點。每個 GROUP 都有一個備份節點,用於備份即將提交硬件處理的那幀原始圖像。VPSS 在以下情況會將緩存隊列隊頭節點的圖像放入備份節點:
− 當隊頭節點的圖像要經過 VPSS 硬件處理時,VPSS 會將其放入備份節點,並替換掉原有圖像。
− 當後端綁定的接收模塊要求 VPSS 將隊頭圖像放入備份節點時,VPSS 也會替換備份節點中的圖像,即使該圖像不經過硬件處理。
低延時:在 VI—VPSS 的在線方案中,編碼器性能足夠的情況下,VPSS 支持按照,以行爲單位,邊採集邊發送的方式,將圖像發送給編碼模塊進行編碼,用來減少 VPSS處理完整幀圖像再發送給編碼模塊過程中,數據的延時時間。這樣的方式即爲低延時方案。5、VI/VPSS 離/在線模式
VI/VPSS 離線模式是指 VI 進行時序解析後將圖像數據寫出到 DDR,VPSS 從DDR 中載入 VI 採集的數據進行圖像處理,是傳統Hi3518/Hi3520D 等芯片的VI/VPSS 的協作模式。
VI/VPSS 在線模式是指 VI 進行時序解析後直接在芯片內部將數據傳遞到 VPSS,中間無 DDR 寫出的過程(少了一次到兩次的內存複製)。在線模式可以省一定的帶寬和內存,降低端到端的延時。需要注意的是,在線模式時,因爲 VI 不寫出數據到 DDR,無法進行CoverEx、OverlayEx、Rotate、LDC 等操作,需要在 VPSS 各通道寫出後再進行Rotate/LDC 等處理,而且有些功能只在離線下能支持,比如 DIS。
通過調用HI_MPI_SYS_Bind函數可以將可與 VI 和 VO/VENC/IVE 等模塊進行綁定,其中前者爲 VPSS 的輸入源(VO),後者爲 VPSS 的接收者。每個 GROUP 僅可與一個輸入源綁定。GROUP 的物理通道有兩種工作模式:AUTO 和 USER,兩種模式間可動態切換。默認的工作模式爲 AUTO,此模式下各通道僅可與一個接收者綁定。USER 模式主要用於對同一通道圖像進行多路編碼的場景。
注:Hi3516A/Hi3518EV200/Hi3519V100 僅支持 USER 工作模式。
VENC 模塊,即視頻編碼模塊。本模塊支持多路實時編碼,且每路編碼獨立,編碼協議和編碼 profile(圖像不同的清晰度標準) 可以不同。本模塊支持視頻編碼同時,調度 Region 模塊對編碼圖像內容進行疊加(OSD)和遮擋。
BP:基本的,清晰度不怎麼樣,但編碼速度快。
MP:主流的,性能平衡。HP:高清的,清晰度最好的。
視頻編碼的流程:典型的編碼流程包括了輸入圖像的接收、圖像內容的遮擋和覆蓋、圖像的編碼、以及碼流的輸出等過程。
碼率控制器:碼率控制器實現對編碼碼率進行控制。
從信息學的角度分析,圖像的壓縮比越低,壓縮圖像的質量越高;圖像壓縮比例越高,壓縮圖像的質量越低。對於場景變化的真實場景,圖像質量穩定,編碼碼率會波動;編碼碼率穩定,圖像質量會波動(例如運動視頻,如果壓縮度過高,就會破壞視頻質量)。以 H.264 編碼爲例,通常圖像 Qp 越低,圖像的質量越好,碼率越高;圖像 Qp (h.264編碼中的一個概念)越高,圖像質量越差,碼率越低。
碼率控制器分別提供了對 H.264\H.265\MJPEG 協議編碼通道 CBR、VBR、FIXQP 等三種碼率控制模式,對圖像質量和碼率進行調節。
CBR(Constant Bit Rate)固定比特率。即在碼率統計時間內保證編碼碼率平穩。碼率穩定主要由兩個量來評估,這兩個量都可以由用戶在創建編碼通道時指定。
VBR(Variable Bit Rate)可變比特率,即允許在碼率統計時間內編碼碼率波動,從而保證編碼圖像質量平穩。以 H.264 編碼爲例,VENC 模塊提供用戶可設置 MaxQp,MinQp,MaxBitrate 和 ChangePos。MaxQp,MinQp 用於控制圖像的質量範圍,MaxBitrate 用於鉗位碼率統計時間內的最大編碼碼率,ChangePos 用於控制開始調整Qp 的碼率基準線。
Fix Qp 固定 Qp 值。在碼率統計時間內,編碼圖像所有宏塊 Qp 值相同,採用用戶設定的圖像 Qp 值,I 幀和 P 幀的 QP 值可以分別設的置。