1、簡介
海思提供的媒體處理軟體平台(Media Process Platform,簡稱 MPP)
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 值可以分别設的置。