Hi3516開(kāi)發(fā)筆記(十):Qt從VPSS中獲取通道圖像數(shù)據(jù)存儲(chǔ)為jpg文件
前言
??上一篇已經(jīng)將himpp套入qt的基礎(chǔ)上進(jìn)行開(kāi)發(fā)。那么qt中拿到frame則是很關(guān)鍵的交互,這是qt與海思可能編解碼交叉開(kāi)發(fā)的關(guān)鍵步驟。
受限制
??因?yàn)橹苯优渲胹ample的vi比較麻煩,確實(shí)是困難的,其實(shí)就是配置驅(qū)動(dòng),所以我們只能從開(kāi)發(fā)板的demo入手,去在相等條件下探測(cè)可能的留,從vpss中拿取后,進(jìn)行軟編碼。
??當(dāng)然,如果不用qt還有一種方式,也就是大量開(kāi)發(fā)海思人員使用的方式,是基于sample寫(xiě)一個(gè)編碼程序,然后使用本地socket交互,其實(shí)絕大部分海思開(kāi)發(fā)者都是這樣開(kāi)發(fā)的,但是他們不涉及與qt的深入交互。
前提條件
??需要移植ffmpeg到海思平臺(tái),可參考博文《FFmpeg開(kāi)發(fā)筆記(十):ffmpeg在ubuntu上的交叉編譯移植到海思HI35xx平臺(tái)》。
Demo演示
??從vpss中獲取一幀圖像,如下圖:
??

??

相關(guān)的API
??(原本整理了一大半自己的習(xí)慣格式,后續(xù)海思看多了,覺(jué)得海思文檔也還行,就是爭(zhēng)對(duì)性的開(kāi)發(fā),無(wú)用信息有點(diǎn)多,所以此處還是用海思的文檔,但是只提取涉及的部分,海思文檔是個(gè)龐大的體系,需要?jiǎng)邮郑饪词呛茈y理解的)。
HI_MPI_VPSS_GetChnFrame:從通道獲取一幀處理完的數(shù)據(jù)
??用戶從通道獲取一幀處理完成的圖像,必須與HI_MPI_VPSS_ReleaseChnFrame()配對(duì)使用。
函數(shù)原型
HI_S32 HI_MPI_VPSS_GetChnFrame(VPSS_GRP VpssGrp,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? VPSS_CHN VpssChn,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? VIDEO_FRAME_INFO_S *pstVideoFrame,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? HI_S32 s32MilliSec);
參數(shù)一:VpssGrou,通道組號(hào),海思芯片通道號(hào),
取值[0,?VPSS_MAX_GRP_NUM];參數(shù)二:VpssChn,通道號(hào),通道組下的通道號(hào),
取值[0,?VPSS_MAX_CHN_NUM];參數(shù)三:pstVideoFrame,幀數(shù)據(jù)的結(jié)構(gòu)體,要取的數(shù)據(jù)就在這個(gè)幀里面,這
是很關(guān)鍵的結(jié)構(gòu)體,稍后是會(huì)深入講解的重點(diǎn);參數(shù)四:s32MilliSec,阻塞時(shí)間,跟其他阻塞有點(diǎn)區(qū)別,-1為阻塞,0為直
接獲取,其他整數(shù)位等待的超時(shí)時(shí)間。
返回值
???

其他注意
??

HI_MPI_VPSS_ReleaseChnFrame:釋放一幀圖像
??釋放之前通過(guò)HI_MPI_VPSS_GetChnFrame獲取獲取的圖像。
函數(shù)原型
HI_S32 HI_MPI_VPSS_ReleaseChnFrame (VPSS_GRP VpssGrp,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?VPSS_CHN VpssChn,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const VIDEO_FRAME_INFO_S *pstVideoFrame);
參數(shù)一:VpssGrou,通道組號(hào),海思芯片通道號(hào),
取值[0,?VPSS_MAX_GRP_NUM],之前獲取使用的是哪個(gè)就哪個(gè);參數(shù)二:VpssChn,通道號(hào),通道組下的通道號(hào),
取值[0,?VPSS_MAX_CHN_NUM];之前獲取使用的是哪個(gè)就哪個(gè);參數(shù)三:pstVideoFrame,幀數(shù)據(jù)的結(jié)構(gòu)體,要取的數(shù)據(jù)就在這個(gè)幀里面,這
是很關(guān)鍵的結(jié)構(gòu)體,稍后是會(huì)深入講解的重點(diǎn);
返回值
??

其他注意
???

相關(guān)的結(jié)構(gòu)體
VIDEO_FRAME_INFO_S:定義視頻圖像幀信息結(jié)構(gòu)體
結(jié)構(gòu)體原型
typedef struct hiVIDEO_FRAME_INFO_S{
? ?VIDEO_FRAME_S stVFrame; // 視頻圖像幀
? ?HI_U32 u32PoolId; // 視頻緩存池ID
? ?MOD_ID_E enModId; // 當(dāng)前幀數(shù)據(jù)是由哪一個(gè)硬件邏輯模塊寫(xiě)出的} VIDEO_FRAME_INFO_S;
VIDEO_FRAME_S:定義視頻原始圖像幀結(jié)構(gòu)體
結(jié)構(gòu)體原型
typedef struct hiVIDEO_FRAME_S{
? ?HI_U32 u32Width; // 圖像寬度
? ?HI_U32 u32Height; // 圖像高度
? ?VIDEO_FIELD_E enField; // 幀場(chǎng)模式
? ?PIXEL_FORMAT_E enPixelFormat; // 視頻圖像像素格式
? ?VIDEO_FORMAT_E enVideoFormat; // 視頻圖像格式
? ?COMPRESS_MODE_E enCompressMode; // 視頻壓縮模式
? ?DYNAMIC_RANGE_E enDynamicRange; // 動(dòng)態(tài)范圍
? ?COLOR_GAMUT_E enColorGamut; // 色域范圍
? ?HI_U32 u32HeaderStride[3]; // 圖像壓縮頭跨距
? ?HI_U32 u32Stride[3]; // 圖像數(shù)據(jù)跨距
? ?HI_U32 u32ExtStride[3]; // 10bit數(shù)據(jù)位寬的圖像,部分格式分開(kāi)存
? ?HI_U64 u64HeaderPhyAddr[3]; // 壓縮頭物理地址
? ?HI_U64 u64HeaderVirAddr[3]; // 壓縮頭虛擬地址,內(nèi)核態(tài)虛擬地址
? ?HI_U64 u64PhyAddr[3]; // 圖像數(shù)據(jù)物理地址
? ?HI_U64 u64VirAddr[3]; // 圖像數(shù)據(jù)虛擬地址,內(nèi)核態(tài)虛擬地址
? ?HI_U64 u64ExtPhyAddr[3]; // 10bit數(shù)據(jù)位寬度的圖像,部分格式分開(kāi)存
? ?HI_U64 u64ExtVirAddr[3]; // 10bit數(shù)據(jù)位寬度的圖像,部分格式分開(kāi)存
? HI_S16 s16OffsetTop; // 圖像頂部剪裁寬度
? ?HI_S16 s16OffsetBottom; // 圖像底部剪裁寬度
? ?HI_S16 s16OffsetLeft; // 圖像左側(cè)剪裁寬度
? ?HI_S16 s16OffsetRight; // 圖像右側(cè)剪裁寬度
? ?HI_U32 u32MaxLuminance; // 顯示圖像的最大亮度
? ?HI_U32 u32MinLuminance; // 顯示圖像的最小亮度
? ?HI_U32 u32TimeRef; // 圖像幀序列號(hào)
? ?HI_U64 u64PTS; // 圖像時(shí)間戳
? ?HI_U64 u64PrivateData; // 私有數(shù)據(jù)
? HI_U32 u32FrameFlag; // 當(dāng)前幀的標(biāo)記,使用FRAME_FLAG_E標(biāo)記
? ?VIDEO_SUPPLEMENT_S stSupplement; // 圖像的補(bǔ)充信息} VIDEO_FRAME_S;
其他注意
??

相關(guān)枚舉
VIDEO_FIELD_E:幀場(chǎng)模式
??

PIXEL_FORMAT_E:視頻圖像像素格式
??

??

VIDEO_FORMAT_E:視頻圖像格式
??

COMPRESS_MODE_E:視頻壓縮模式
??

DYNAMIC_RANGE_E:動(dòng)態(tài)范圍
??

COLOR_GAMUT_E:色域范圍
??

VIDEO_SUPPLEMENT_S:圖像的補(bǔ)充信息
??

Demo
void HiMppManager::testGetVPssFrame(){
? ?VIDEO_FRAME_INFO_S videoFrameInfoS;#if 0
? ?// 搜索開(kāi)開(kāi)發(fā)板用了哪個(gè)通道(應(yīng)該只有2個(gè)攝像頭,綁定了vpss)
? ?// 結(jié)果:探測(cè)到開(kāi)發(fā)板在snap抓圖模式下在通道組0通道0下有圖片
? ?for(int groupIndex = 0; groupIndex < VPSS_MAX_GRP_NUM; groupIndex++)
? ?{
? ? ? ?for(int channelIndex = 0; channelIndex < VPSS_MAX_CHN_NUM; channelIndex++)
? ? ? ?{
? ? ? ? ? ?HI_S32 s32MilliSec = 100;
? ? ? ? ? ?HI_S32 ret = HI_MPI_VPSS_GetChnFrame(groupIndex, channelIndex, &videoFrameInfoS, s32MilliSec);
? ? ? ? ? ?if(ret == 0)
? ? ? ? ? ?{
? ? ? ? ? ? ? ?LOG << QString("Succeed to get HI_MPI_VPSS_GetChnFrame(%1, %2, &videoFrameInfoS, %3)")
? ? ? ? ? ? ? ? ? ? ? .arg(groupIndex)
? ? ? ? ? ? ? ? ? ? ? .arg(channelIndex)
? ? ? ? ? ? ? ? ? ? ? .arg(s32MilliSec);
? ? ? ? ? ? ? ?break;#if 0
? ? ? ? ? ?}else{
? ? ? ? ? ? ? ?LOG << ?QString("Failed to get HI_MPI_VPSS_GetChnFrame(%1, %2, &videoFrameInfoS, %3): %4")
? ? ? ? ? ? ? ? ? ? ? ?.arg(groupIndex)
? ? ? ? ? ? ? ? ? ? ? ?.arg(channelIndex)
? ? ? ? ? ? ? ? ? ? ? ?.arg(s32MilliSec)
? ? ? ? ? ? ? ? ? ? ? ?.arg(ret);#endif
? ? ? ? ? ?}
? ? ? ?}
? ?}#endif
? ?while(HI_MPI_VPSS_GetChnFrame(0, 0, &videoFrameInfoS, -1) == 0)
? ?{
? ? ? ?LOG << "get frame";
? ? ? ?LOG << videoFrameInfoS.stVFrame.enPixelFormat ? ? ? ? ? ?<< "PIXEL_FORMAT_YVU_PLANAR_420:" << (int)PIXEL_FORMAT_YVU_PLANAR_420 ? ? ? ? ? ?<< "PIXEL_FORMAT_YVU_SEMIPLANAR_420:" << (int)PIXEL_FORMAT_YVU_SEMIPLANAR_420;
? ? ? ?LOG << videoFrameInfoS.stVFrame.enVideoFormat;
? ? ? ?HI_MPI_VPSS_ReleaseChnFrame(0, 0, &videoFrameInfoS);
? ? ? ?LOG << "release frame"; ? ?}}
入坑
入坑一:獲取vpss圖像一定幀數(shù)后無(wú)法再獲取
問(wèn)題
??使用海思sdk獲取圖像后,多次獲取后,大概20次左右就獲取失敗了。
原因
??海思獲取圖像后,需要釋放,是占用了緩存區(qū)。
??海思的HI_MPI_VPSS_GetChanFrame與Hi_MPI_VPSS_ReleaseChnFrame要成對(duì)使用。
解決方法
??
