当前位置:网站首页>海思3559萬能平臺搭建:獲取數據幀修改後編碼
海思3559萬能平臺搭建:獲取數據幀修改後編碼
2022-06-30 12:15:00 【快跑bug來啦】
前言
有了這麼長的鋪墊和反複的啃sample,現在開始搭建自己的平臺就底氣多了,倒也不至於萬能平臺哈哈,只是在完成配置文件的功能後,可以不用改代碼重新編譯,就可以實現多場景多平臺多功能下的使用了
獲取通道圖像
萬裏長征第一步,在vi暫時沒有改動依靠傳感器的前提下,自然就是找個合適的比特置從vpss處獲取圖像信息了,查看vpss處有關api,首先想到的自然是HI_MPI_VPSS_SendFrame和HI_MPI_VPSS_GetChnFrame(HI_MPI_VPSS_GetGrpFrame是從group獲得的原始圖像,主要於高清設備解碼回放,要求暫停、步進時等場景,PIP 層和普通視頻層上的兩個通道顯示同一幀圖像)
HI_MPI_VPSS_SendFrame
該函數的應用場景在文檔裏並沒有詳細說明,默認開發者是熟悉海思平臺的開發流程的,但是很明顯,對於剛上手的小白來說,一脚就踩進了文字描述的大坑(個人理解問題),用戶向vpss發送數據,怎麼理解呢,數據哪來,肯定是vi來的,難道這相當於使能數據發送(怎麼可能這麼不智能)?調來一用果然各種報錯,完全沒有體會到,在平臺各個部分配置完成後平臺就可以自行運轉數據流動的功能(甭管流沒溜出去總之在流),一番嘗試無果後才明白選對group和chnl就可以直接get數據信息了
HI_MPI_VPSS_GetChnFrame
/* *描述 : 用戶從通道獲取一幀處理完成的圖像。 *參數 : VpssGrp VPSS GROUP 號。取值範圍:[0, VPSS_MAX_GRP_NUM) 輸入 * VpssChn VPSS 通道號。取值範圍:[0, VPSS_MAX_CHN_NUM) 輸入 * pstVideoFrame 圖像信息 輸出 * s32MilliSec 超時時間 輸入 *返回值: 成功返回0,失敗參考錯誤碼 *注意 : GROUP 必須已創建。 該接口適用於 VPSS 所有通道,包括物理通道與擴展通道。 只有在 USER 模式下,並且隊列深度不為 0,才能獲取到圖像。 chnl設置裏u32Depth不能為0. 調用該接口獲取圖像,不會對後端綁定的模塊有影響。如後端綁定 VO 顯示,可以在顯示過程中獲取圖像,VO 仍正常顯示,不會受到影響。 當 s32MilliSec 設為-1 時,錶示阻塞模式,程序一直等待,直到獲取到圖像才返回。如果 s32MilliSec 等於 0 時,錶示非阻塞模式。 如果 s32MilliSec 大於 0 時,錶示超時等待模式,參數的單比特是毫秒,指超時時間,在此時間內如果沒有獲取到圖像,則超時返回。 解碼回放場景,由於不允許出現丟幀,VPSS 只要有一個通道不處理新圖像(通道已使能),則整個 VPSS 不處理新圖像。例如說使能了通道 0 和通道 1, 兩者都不綁定後端,通道圖像隊列長度都設為 2,此時從通道 0 中最多獲取出 2 幀已緩存的圖像,因為通道 1 緩存 2 幀後未處理新圖像,所以 VPSS 不會再處理新圖像 */
HI_S32 HI_MPI_VPSS_GetChnFrame(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VIDEO_FRAME_INFO_S *pstVideoFrame, HI_S32 s32MilliSec);
最直接的想法肯定是重新開個線程,while1去不斷get,然後處理,發送,那麼第一個問題來了,pthread_create需要傳那些參數呢?之前的線程經常都是幹獨立的事情或者最多傳一個參數。最少也需要傳遞group和chn兩個參數進來啊,雖然是兩個int類型可以手動指定,但為了代碼維護和規範,還是使用通用做法吧。此時venc的sample還沒有重構過,直接用用全局變量太粗暴了,為了線程的安全穩定,通過結構體傳參是個不錯的選擇(親自寫過自然覺得容易,CV多了還真的連常識都不知道)
#include <pthread.h>
int pthread_create(
pthread_t *restrict tidp, //新創建的線程ID指向的內存單元。
const pthread_attr_t *restrict attr, //線程屬性,默認為NULL
void *(*start_rtn)(void *), //新創建的線程從start_rtn函數的地址開始運行
void *restrict arg //默認為NULL。若上述函數需要參數,將參數放入結構中並將地址作為arg傳入。
);
暫時定義了個專門用來傳參的結構體
/* 傳遞給線程的結構體 */
typedef struct video_process_para
{
VPSS_GRP VpssGrp ;
VPSS_CHN VpssChn ;
}video_process_s;
video_process_s stv_process_test ;
memset(&stv_process_test,0,sizeof( video_process_s));
而參數 pstVideoFrame是輸出,聲明下就好了
就可以開線程隨意操作了
if(yuvtestEnable)
{
pthread_t video_process_id;
stv_process_test.VpssGrp = VpssGrp;
stv_process_test.VpssChn = VpssChn[1];
s32Ret=pthread_create(&video_process_id, NULL, &video_process_test_task,(HI_VOID*)&stv_process_test);
if(s32Ret != 0)
{
SAMPLE_PRT("pthread video_process create failed\n");
return -HI_FAILURE;
}
pthread_detach(video_process_id);
}
代碼是後來粘過來的,並不是開發過程中,所以。。忽略掉注釋和住掉的部分看哈
/* *描述 :用於處理圖像信息的線程 *參數 :arg 為自定義結構video_process_s,VPSS_GRP和VPSS_CHN用於傳參給HI_MPI_VPSS_GetChnFrame *返回值:無 *注意 :HI_MPI_VPSS_GetChnFrame完必須釋放,否則再次獲取VB會報錯 */
HI_VOID *video_process_test_task(HI_VOID *arg)
{
HI_S32 cnt = 0;
HI_S32 s32Ret;
VIDEO_FRAME_INFO_S stVideoFrame;
video_process_s* pstPara;
pstPara = (video_process_s*)arg;
sleep(1);
memset(&stVideoFrame,0,sizeof(VIDEO_FRAME_INFO_S));
while(cnt <= 10)
{
s32Ret = HI_MPI_VPSS_GetChnFrame(pstPara->VpssGrp, pstPara->VpssChn, &stVideoFrame,1000);
if(s32Ret != HI_SUCCESS)
{
SAMPLE_PRT("%dVPSS_GetChnFrame err for %#x!\n", cnt,s32Ret);
cnt++;
}
else
{
//HI_MPI_VPSS_ReleaseChnFrame(pstPara->VpssGrp, pstPara->VpssChn, &stVideoFrame);//不釋放會導致後續vb崩潰
goto DEAL;
}
}
goto EXIT;
DEAL:
// deal_myself_osd(arg);
// deal_myself_yuv2rgb(arg);
deal_myself(arg);
EXIT:
pthread_exit(0);
}
這麼搞沒第二下就重啟報錯了,
VB占用解决方法
很明顯這是資源沒有釋放唄,思路三種:
第一種最粗暴的就是强制銷毀VB,一勞永逸,但是會屏蔽開發中的很多漏洞,學習階段還是不這麼搞
第二種方法也類似,是在main最開始做一個資源的釋放,畢竟海思自己初始化之前不也有去初始化的操作嗎?
第三種還是正向解决比較好,規範寫法最優,更何况這個問題相對後面重構後的坑來說還是直接多了的,畢竟,就加了一句啊,嘗試釋放了通道的信息後馬上就好了
HI_MPI_VPSS_ReleaseChnFrame
簡單的做個處理前的判斷,要是可以讀到信息就進行我們的處理,連著幾次讀不到就歇著吧您
/* *描述 :用於處理圖像信息的線程 *參數 :arg 為自定義結構video_process_s,VPSS_GRP和VPSS_CHN用於傳參給HI_MPI_VPSS_GetChnFrame *返回值:無 *注意 :HI_MPI_VPSS_GetChnFrame完必須釋放,否則再次獲取VB會報錯 */
HI_VOID *video_process_test_task(HI_VOID *arg)
{
HI_S32 cnt = 0;
HI_S32 s32Ret;
VIDEO_FRAME_INFO_S stVideoFrame;
video_process_s* pstPara;
pstPara = (video_process_s*)arg;
sleep(1);
memset(&stVideoFrame,0,sizeof(VIDEO_FRAME_INFO_S));
while(cnt <= 10)
{
s32Ret = HI_MPI_VPSS_GetChnFrame(pstPara->VpssGrp, pstPara->VpssChn, &stVideoFrame,1000);
if(s32Ret != HI_SUCCESS)
{
SAMPLE_PRT("%dVPSS_GetChnFrame err for %#x!\n", cnt,s32Ret);
cnt++;
}
else
{
HI_MPI_VPSS_ReleaseChnFrame(pstPara->VpssGrp, pstPara->VpssChn, &stVideoFrame);//不釋放會導致後續vb崩潰
goto DEAL;
}
}
goto EXIT;
DEAL:
// deal_myself_osd(arg);
// deal_myself_yuv2rgb(arg);
deal_myself(arg);
EXIT:
pthread_exit(0);
}
到了此處好像第一個問題就解决了?可以捕獲到圖片信息了,到時候調用自己的庫deal_myself處理唄?處理完流程也是自動的,想想就激動,還是不難嘛~
sample的自動智能都是建立在綁定的基礎上的,自己截了數據玩了玩釋放,後續誰管你啊!
發送編碼圖像
首先需要取消原來vpss和venc的綁定,要不然人家流轉的飛起,你自娛自樂
HI_MPI_VENC_SendFrame
/* *描述 :支持用戶發送原始圖像進行編碼 *參數 :VeChn 編碼通道號。取值範圍:[0, VENC_MAX_CHN_NUM) pstFrame 原始圖像信息結構指針。 s32MilliSec 發送圖像超時時間。取值範圍:[-1,+ ∞ ) -1:阻塞。 0:非阻塞。大於 0:超時時間。 *返回值:成功返回0,失敗參考錯誤碼 *注意 : 此接口支持用戶發送圖像至編碼通道。 如果 s32MilliSec 小於-1,返回 HI_ERR_VENC_ILLEGAL_PARAM。 用戶發送原始圖像必須為 Semi-planar YVU 4:2:0 或 Semi-planar YVU 4:2:2 或PIXEL_FORMAT_YUV_400 格式。H.264/H.265 編碼通道支持接收 Semi-plannarYVU 4:2:0 或 PIXEL_FORMAT_YUV_400 圖像, JPEG/MJPEG 編碼通道支持接收Semi-plannar YVU 4:2:0、Semi-plannar YVU 4:2:2 或 PIXEL_FORMAT_YUV_400圖像。 視頻輸入的原始圖像大小必須不小於編碼通道的大小。 調用該接口發送圖像,用戶需要保證編碼通道已創建且開啟接收輸入圖像。 */
HI_S32 HI_MPI_VENC_SendFrame(VENC_CHN VeChn, const VIDEO_FRAME_INFO_S *pstFrame, HI_S32 s32MilliSec);
一定要看注意看注意看注意!這裏寫的清清楚楚,網上好多博客說海思沒有官方聲明,但實際只支持什麼什麼格式(也可能版本不一致導致)後續因為格式問題踩了大坑
/* *描述 :線程裏用於處理圖像信息 *參數 :arg 為自定義結構video_process_s,VPSS_GRP和VPSS_CHN用於傳參給HI_MPI_VPSS_GetChnFrame *返回值:無 *注意 :HI_MPI_VPSS_GetChnFrame完必須釋放,否則再次獲取VB會報錯 VIDEO_FRAME_INFO_S裏的虛擬地址不可以直接使用,必須通過物理地址HI_MPI_SYS_Mmap映射後才可以作為數據存放地址用 用完同樣需要HI_MPI_SYS_Munmap解映射 */
HI_VOID deal_myself(HI_VOID *arg)
{
HI_S32 s32Ret;
VIDEO_FRAME_INFO_S stVideoFrame;
// VIDEO_FRAME_INFO_S* pstVideoFrame = &stVideoFrame;
video_process_s* pstPara;
pstPara = (video_process_s*)arg;
while(1)
{
s32Ret = HI_MPI_VPSS_GetChnFrame(pstPara->VpssGrp, pstPara->VpssChn, &stVideoFrame,1000);
// SAMPLE_PRT("deal_myself is pstPara->VpssChn is %d!\n",pstPara->VpssChn);
// sleep(1);
if(s32Ret != HI_SUCCESS)
{
// SAMPLE_PRT("VPSS_GetChnFrame err for %#x!\n",s32Ret);//while1打印太多
}
// printf("u32TimeRef is %d\r\n",pstVideoFrame->stVFrame.u32TimeRef);
else
{
/* ................................圖像處理 */
s32Ret = HI_MPI_VENC_SendFrame(pstPara->VpssChn, &stVideoFrame,1000);
// printf("u32TimeRef is %d\r\n",pstVideoFrame->stVFrame.u32TimeRef);
HI_MPI_VPSS_ReleaseChnFrame(pstPara->VpssGrp, pstPara->VpssChn, &stVideoFrame);
}
}
}
更改下sleep時間,相當於改了幀率,就能很清楚的知道最後保存下來的文件是處理過得了,畢竟sample有兩個通道,我們只謔謔了通道1,大小小了很多嘛
注意事項
vpss通道的設置中stVpssChnAttr.u32Depth此時不能為0,否則圖像隊列會一直為空
結論
合適的比特置找見了,下一步就開始自己做一些簡單的圖像處理咯!
边栏推荐
- 「运维有小邓」用户个人资料管理
- Map集合
- 实现多方数据安全共享,解决普惠金融信息不对称难题
- 使用深度学习进行生物网络分析
- AGCO AI frontier promotion (6.30)
- MySQL 复合查询
- [cf] 803 div2 A. XOR Mixup
- Object mapping - mapping Mapster
- R language ggplot2 visualization: gganimate package is based on Transition_ Time function to create dynamic scatter animation (GIF)
- Statistics on the number of closed Islands
猜你喜欢

A Generic Deep-Learning-Based Approach for Automated Surface Inspection-论文阅读笔记

3D视觉检测在生产流水的应用有哪些

A review of quantum neural networks 2022 for generating learning tasks

21、wpf之绑定使用小记

After the node is installed in the NVM, the display is not internal or external when the NPM instruction is used

How can c write an SQL parser

Joplin实现样式更改

海思3559万能平台搭建:获取数据帧修改后编码

Embedded SIG | 多 OS 混合部署框架

爱可可AI前沿推介(6.30)
随机推荐
Four Misunderstandings of Internet Marketing
剑指 Offer 05. 替换空格: 把字符串 s 中的每个空格替换成“%20“
Redis - SDS simple dynamic string
VScode选中多个单词
通过EF Core框架根据SQL Server数据库表生成实体类
Achieve secure data sharing among multiple parties and solve the problem of asymmetric information in Inclusive Finance
21、wpf之绑定使用小记
Serial communication interface 8250
Object mapping - mapping Mapster
1175. 质数排列 : 乘法原理运用题
Time function and clock_ Differences between gettime() functions
The website with id 0 that was requested wasn‘t found. Verify the website and try again
MySQL 表的内连和外连
The sci-fi ideas in these movies have been realized by AI
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
OpenMLDB Meetup No.4 会议纪要
iServer发布ES服务查询设置最大返回数量
A Generic Deep-Learning-Based Approach for Automated Surface Inspection-论文阅读笔记
Shutter 007 input field from zero
R language ggplot2 visualization: use ggplot2 visualization scatter diagram and the color parameter in AES function to specify that data points in different groups are displayed in different colors