Hi3516開發筆記(十):Qt從VPSS中獲取通道影像資料儲存為jpg檔案

21497936發表於2022-08-12


前言

  上一篇已經將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_GetChanFrameHi_MPI_VPSS_ReleaseChnFrame要成對使用。

解決方法

   在這裡插入圖片描述


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70010283/viewspace-2910202/,如需轉載,請註明出處,否則將追究法律責任。

相關文章