目錄
前言
01 測試Demo大致流程圖
02 代碼分析
2.1 VI設備初始化
2.2 使能通道 ——?RK_MPI_VI_EnableChn
?2.3 VI 和 VENC綁定
2.4 創建?編碼線程
?
前言
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
從本章開始我們將要學習嵌入式音視頻的學習了 ,使用的瑞芯微的開發板
🎬 個人主頁:@ChenPi
🐻推薦專欄1: 《C++_@ChenPi的博客-CSDN博客》????
🔥 推薦專欄2: 《Linux C應用編程(概念類)_@ChenPi的博客-CSDN博客》???
🛸推薦專欄3:《嵌入式音視頻_@ChenPi的博客-CSDN博客》
🌺本篇簡介 ?:使用RV1126進行編碼測試??
首先我們使用的硬件為瑞芯微的RV1126
kmedia是RK官方封裝一層簡易的API,把RGA、MPP、RKNN等等這些接口封裝成高級的接口
該平臺支持以下功能:
- VI(輸入視頻捕獲)
- VO(視頻輸出顯示)
- AI(音頻采集)、AO(音頻輸出)
- VENC(H.265/H.264/JPEG/MJPEG編碼)
- VDEC(H.265/H.264/JPEG、MJPEG 解碼)
- RGA視頻處理(包括旋轉、縮放、裁剪)
- AENC(音頻編碼)、ADEC(音頻解碼)、
- MD(移動偵測)
- OD(遮擋偵測)
- VMIX(視頻合成)
- MUXER(視頻封裝)
- VP(視頻一入四出)

01 測試Demo大致流程圖
??
因為這個測試Demo主要是編碼進行視頻編碼
所以只用到VI和VENC?
- VI(輸入視頻捕獲)
- VENC(H.265/H.264/JPEG/MJPEG編碼)
02 代碼分析
2.1 VI設備初始化
VI設備初始化有兩步
- 設置通道屬性
- 使能通道
?設置通道屬性 —— RK_MPI_VI_SetChnAttr
設置通道的屬性關鍵在于VI_CHN_ATTR_S結構體
結構體原型:
typedef struct rkVI_CHN_ATTR_S {const RK_CHAR *pcVideoNode; //video節點路徑RK_U32 u32Width; //分辨率寬度RK_U32 u32Height; //分辨率高度IMAGE_TYPE_E enPixFmt; //(VI格式) RK_U32 u32BufCnt; // 映射類型默認是:MMAPVI_CHN_BUF_TYPE enBufType; // VI通道模式VI_CHN_WORK_MODE enWorkMode; //VI工作模式
} VI_CHN_ATTR_S;
需要注意的點:
結構體中的enBufType //VI 捕 捉 視 頻 的 類 型? :
- DMA 模 式(VI_CHN_BUF_TYPE_DMA)?
- MMAP 模式(VI_CHN_BUF_TYPE_MMAP)
DMA:指的是直接訪問內存的方式,相當于音視頻數據直接從硬件傳輸到內存里面。這種方式的優點就
是兩邊傳輸的速度非常之快,但缺點就是非常消耗硬件資源,對硬件外設資源要求較高。
MMAP:指的是內存映射,這種方式就是把硬件外設、磁盤的文件映射到虛擬內存上面。然后用戶只需
要對虛擬內存進行讀寫操作就可以對硬件外設進行操作了。這種方法的優點是用戶不需要直接操作硬件就能夠修改硬件的內容,換言之就是對硬件的消耗沒那么大。
但是缺點就是:
第一,它的讀寫速度相對 DMA來說沒那么快;
第二,有時候硬件寫到虛擬內存的數據可能會出現丟失情況,導致數據出現丟失的情況。
2.2 使能通道 ——?RK_MPI_VI_EnableChn
VENC的初始化:關鍵在于VENC_CHN_ATTR_S結構體,這個結構體是VENC設置的結構體
RV1126 編碼器參數結構體包含在 VENC 通道屬性結構體里面,我們可以看到 VENC 通道結
構 體 里 面 包 含 三 個 重 要 結 構 體 : 分 別 是
- VENC_ATTR_S( 編 碼 器 基 礎 屬 性 結 構 體 )?
- VENC_RC_ATTR_S(編碼碼率控制屬性結構體)
- VENC_GOP_ATTR_S(編碼器 GOP 屬性結構體)
設置完上述成員變量后,則使用RK_MPI_VENC_CreateChn創建編碼層。
?2.3 VI 和 VENC綁定
設置完VI模塊和VENC模塊后,需要進行綁定VI和VENC才能夠正常采集到編碼數據。
采集的時候用到的結構體·MPP_CHN_S
typedef struct rkMPP_CHN_S {MOD_ID_E enModId;RK_S32 s32DevId;RK_S32 s32ChnId;
} MPP_CHN_S;
其中MPP_CHN_S的enModId是模塊的ID、 s32ChnId是通道id。
這里分別創建兩個MPP_CHN_S結構體,
- VI的MPP_CHN_S,它的enModId選擇的是RK_ID_VI,s32Id應該和VI創建的ID進行適配;
- VENC的MPP_CHN_S,它的enModId選擇的是RK_ID_VENC,s32ChnId和VENC創建的Id對應。
創建完兩個MPP_CHN_S結構體后,利用RK_MPI_SYS_BIND把VI和VENC進行綁定。
2.4 創建?編碼線程
從collect_venc_thread線程主要作用是獲取VENC編碼的碼流數據,并實時保存到H264文件。
在這個線程里面,有幾個重要的API需要講解:
RK_MPI_SYS_GetMediaBuffer的作用是獲取對應通道的數據,
這個API第一個參數是模塊ID,第二個參數是通道ID,第三個參數阻塞時間這里默認是-1不阻塞。
獲取VENC通道的數據后,這其中
- RK_MPI_MB_GetPtr是獲取VENC緩沖區數據,
- RK_MPI_MB_GetSize是獲取VENC的緩沖區長度,并把緩沖區數據fwrite寫到H264文件。?