Hi3516開發筆記(十):Qt從VPSS中獲取通道圖像數據存儲爲jpg文件

前言

  上一篇已經將himpp套入qt的基礎上進行開發。那麼qt中拿到frame則是很關鍵的交互,這是qt與海思可能編解碼交叉開發的關鍵步驟。

 

受限制

  因爲直接配置sample的vi比較麻煩,確實是困難的,其實就是配置驅動,所以我們只能從開發板的demo入手,去在相等條件下探測可能的留,從vpss中拿取後,進行軟編碼。
  當然,如果不用qt還有一種方式,也就是大量開發海思人員使用的方式,是基於sample寫一個編碼程序,然後使用本地socket交互,其實絕大部分海思開發者都是這樣開發的,但是他們不涉及與qt的深入交互。

 

前提條件

  需要移植ffmpeg到海思平臺,可參考博文《FFmpeg開發筆記(十):ffmpeg在ubuntu上的交叉編譯移植到海思HI35xx平臺》。

 

Demo演示

  從vpss中獲取一幀圖像,如下圖:
  在這裏插入圖片描述
  在這裏插入圖片描述

 

相關的API

  (原本整理了一大半自己的習慣格式,後續海思看多了,覺得海思文檔也還行,就是爭對性的開發,無用信息有點多,所以此處還是用海思的文檔,但是隻提取涉及的部分,海思文檔是個龐大的體系,需要動手,光看是很難理解的)。

HI_MPI_VPSS_GetChnFrame:從通道獲取一幀處理完的數據

  用戶從通道獲取一幀處理完成的圖像,必須與HI_MPI_VPSS_ReleaseChnFrame()配對使用。

函數原型

HI_S32 HI_MPI_VPSS_GetChnFrame(VPSS_GRP VpssGrp,
                               VPSS_CHN VpssChn,
                               VIDEO_FRAME_INFO_S *pstVideoFrame,
                               HI_S32 s32MilliSec);
  • 參數一:VpssGrou,通道組號,海思芯片通道號,
    取值[0, VPSS_MAX_GRP_NUM];
  • 參數二:VpssChn,通道號,通道組下的通道號,
    取值[0, VPSS_MAX_CHN_NUM];
  • 參數三:pstVideoFrame,幀數據的結構體,要取的數據就在這個幀裏面,這
    是很關鍵的結構體,稍後是會深入講解的重點;
  • 參數四:s32MilliSec,阻塞時間,跟其他阻塞有點區別,-1爲阻塞,0爲直
    接獲取,其他整數位等待的超時時間。

返回值

   在這裏插入圖片描述

其他注意

  在這裏插入圖片描述

HI_MPI_VPSS_ReleaseChnFrame:釋放一幀圖像

  釋放之前通過HI_MPI_VPSS_GetChnFrame獲取獲取的圖像。

函數原型

HI_S32 HI_MPI_VPSS_ReleaseChnFrame (VPSS_GRP VpssGrp,
                                    VPSS_CHN VpssChn,
                                    const VIDEO_FRAME_INFO_S *pstVideoFrame);
  • 參數一:VpssGrou,通道組號,海思芯片通道號,
    取值[0, VPSS_MAX_GRP_NUM],之前獲取使用的是哪個就哪個;
  • 參數二:VpssChn,通道號,通道組下的通道號,
    取值[0, VPSS_MAX_CHN_NUM];之前獲取使用的是哪個就哪個;
  • 參數三:pstVideoFrame,幀數據的結構體,要取的數據就在這個幀裏面,這
    是很關鍵的結構體,稍後是會深入講解的重點;

返回值

  在這裏插入圖片描述

其他注意

   在這裏插入圖片描述

 

相關的結構體

VIDEO_FRAME_INFO_S:定義視頻圖像幀信息結構體

結構體原型

typedef struct hiVIDEO_FRAME_INFO_S
{
    VIDEO_FRAME_S stVFrame;		// 視頻圖像幀
    HI_U32 u32PoolId;			// 視頻緩存池ID
    MOD_ID_E enModId;			// 當前幀數據是由哪一個硬件邏輯模塊寫出的
} VIDEO_FRAME_INFO_S;

VIDEO_FRAME_S:定義視頻原始圖像幀結構體

結構體原型

typedef struct hiVIDEO_FRAME_S
{
    HI_U32 u32Width;					// 圖像寬度
    HI_U32 u32Height;					// 圖像高度
    VIDEO_FIELD_E enField;				// 幀場模式
    PIXEL_FORMAT_E enPixelFormat;		// 視頻圖像像素格式
    VIDEO_FORMAT_E enVideoFormat;		// 視頻圖像格式
    COMPRESS_MODE_E enCompressMode;		// 視頻壓縮模式
    DYNAMIC_RANGE_E enDynamicRange;		// 動態範圍
    COLOR_GAMUT_E enColorGamut;			// 色域範圍
    HI_U32 u32HeaderStride[3];			// 圖像壓縮頭跨距
    HI_U32 u32Stride[3];				// 圖像數據跨距
    HI_U32 u32ExtStride[3];				// 10bit數據位寬的圖像,部分格式分開存
    HI_U64 u64HeaderPhyAddr[3];			// 壓縮頭物理地址
    HI_U64 u64HeaderVirAddr[3];			// 壓縮頭虛擬地址,內核態虛擬地址
    HI_U64 u64PhyAddr[3];				// 圖像數據物理地址
    HI_U64 u64VirAddr[3];				// 圖像數據虛擬地址,內核態虛擬地址
    HI_U64 u64ExtPhyAddr[3];			// 10bit數據位寬度的圖像,部分格式分開存
    HI_U64 u64ExtVirAddr[3];			// 10bit數據位寬度的圖像,部分格式分開存
   HI_S16 s16OffsetTop;					// 圖像頂部剪裁寬度
    HI_S16 s16OffsetBottom;				// 圖像底部剪裁寬度
    HI_S16 s16OffsetLeft;				// 圖像左側剪裁寬度
    HI_S16 s16OffsetRight;				// 圖像右側剪裁寬度
    HI_U32 u32MaxLuminance;				// 顯示圖像的最大亮度
    HI_U32 u32MinLuminance;				// 顯示圖像的最小亮度
    HI_U32 u32TimeRef;					// 圖像幀序列號
    HI_U64 u64PTS;						// 圖像時間戳
    HI_U64 u64PrivateData;				// 私有數據
   HI_U32 u32FrameFlag;					// 當前幀的標記,使用FRAME_FLAG_E標記
    VIDEO_SUPPLEMENT_S stSupplement;	// 圖像的補充信息
} VIDEO_FRAME_S;

其他注意

  在這裏插入圖片描述

 

相關枚舉

VIDEO_FIELD_E:幀場模式

  在這裏插入圖片描述

PIXEL_FORMAT_E:視頻圖像像素格式

  在這裏插入圖片描述
  在這裏插入圖片描述

VIDEO_FORMAT_E:視頻圖像格式

  在這裏插入圖片描述

COMPRESS_MODE_E:視頻壓縮模式

  在這裏插入圖片描述

DYNAMIC_RANGE_E:動態範圍

  在這裏插入圖片描述

COLOR_GAMUT_E:色域範圍

  在這裏插入圖片描述

VIDEO_SUPPLEMENT_S:圖像的補充信息

  在這裏插入圖片描述

 

Demo

void HiMppManager::testGetVPssFrame()
{
    VIDEO_FRAME_INFO_S videoFrameInfoS;
#if 0
    // 搜索開開發板用了哪個通道(應該只有2個攝像頭,綁定了vpss)
    // 結果:探測到開發板在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圖像一定幀數後無法再獲取

問題

  使用海思sdk獲取圖像後,多次獲取後,大概20次左右就獲取失敗了。

原因

  海思獲取圖像後,需要釋放,是佔用了緩存區。
  海思的HI_MPI_VPSS_GetChanFrame與Hi_MPI_VPSS_ReleaseChnFrame要成對使用。

解決方法

  

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