下面將給出Hi3559AV100外接UVC/MJPEG相機實時采圖設計的整體流程,主要實現(xiàn)是通過V4L2接口將UVC/MJPEG相機采集的數(shù)據送入至MPP平臺,經過VDEC、VPSS、VO最后通過HDMI的輸出,給出(二)V4L2接口的實現(xiàn)。 可以先參照前面隨筆介紹(一)Linux USB攝像頭驅動加載與分析:https://www.cnblogs.com/iFrank/p/14399421.html 板載平臺:BOXER-8410AI 芯片型號:Hi3559AV100 相機型號:Logitch c270 開發(fā)環(huán)境:VM15.5+ubuntu16.04+Hilinux 1、V4L2接口說明V4L2是Video for linux2的簡稱,為linux中關于視頻設備的內核驅動。在Linux中,視頻設備是設備文件,可以像訪問普通文件一樣對其進行讀寫,攝像頭在/dev/video*下,如果只有一個視頻設備,通常為/dev/video0。V4L2是內核提供給應用程序訪問音、視頻驅動的統(tǒng)一接口。V4L2 的相關定義包含在頭文件<linux/videodev2.h> 中。 V4L2 支持兩種方式來采集圖像:內存映射(mmap)和直接讀取方式(read)。V4L2 在/usr/include/linux/videodev2.h 文件下定義了一些重要的數(shù)據結構,在采集圖像的過程中,就是通過對這些數(shù)據的操作來獲得最終的圖像數(shù)據。Linux 系統(tǒng) V4L2 使能可在內核編譯階段配置,默認情況下是在 make menuconfig 是打開的。應用程序可以通過 V4L2 進行視頻采集。V4L2 支持內存映射(mmap)方式和直接讀取方式(read)方式采集數(shù)據。前者
一般用于連續(xù)的視頻數(shù)據采集,后者常用靜態(tài)圖片數(shù)據采集。v4l2 中不僅定義了通用 API 元素,圖像的格式,輸入/輸出方法,還定義了Linux 內核驅動處理視頻信息的一系列接口,這些接口主要有:
視頻采集接口——Video Capture interface;
視頻輸出接口——Video Output Interface;
視頻覆蓋/預覽接口——Video Overlay Interface;
視頻輸出覆蓋接口——Video Output Overlay Interface;
編解碼接口——Codec Interface
IOCTL的實現(xiàn)V4L2的控制 打開視頻設備后,可以設置該視頻設備的屬性,例如裁剪、縮放等。這一步是可選的。在Linux編程中,一般使用ioctl函數(shù)來對設備的I/O通道進行管理:
extern int ioctl (int __fd, unsigned long int __request, …) __THROW;
__fd:設備的ID,例如剛才用open函數(shù)打開視頻通道后返回的cameraFd;
__request:具體的命令標志符。
在進行V4L2開發(fā)中,一般會用到以下的命令標志符:
1:分配內存 2 VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的數(shù)據緩存轉換成物理地址 3 VIDIOC_QUERYCAP:查詢驅動功能 4 VIDIOC_ENUM_FMT:獲取當前驅動支持的視頻格式 5 VIDIOC_S_FMT:設置當前驅動的頻捕獲格式 6 VIDIOC_G_FMT:讀取當前驅動的頻捕獲格式 7 VIDIOC_TRY_FMT:驗證當前驅動的顯示格式 8 VIDIOC_CROPCAP:查詢驅動的修剪能力 9 VIDIOC_S_CROP:設置視頻信號的邊框 10 VIDIOC_G_CROP:讀取視頻信號的邊框 11 VIDIOC_QBUF:把數(shù)據放回緩存隊列 12 VIDIOC_DQBUF:把數(shù)據從緩存中讀取出來 13 VIDIOC_STREAMON:開始視頻顯示函數(shù) 14 VIDIOC_STREAMOFF:結束視頻顯示函數(shù) 15 VIDIOC_QUERYSTD:檢查當前視頻設備支持的標準,例如PAL或NTSC。 這些IO調用,有些是必須的,有些是可選擇的,其命令標志符在在頭文件<linux/videodev2.h> 定義,具體如下: 1 #define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability) 2 #define VIDIOC_RESERVED _IO('V', 1) 3 #define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc) 4 #define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format) 5 #define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format) 6 #define VIDIOC_REQBUFS _IOWR('V', 8, struct v4l2_requestbuffers) Logitch c270支持的像素格式有兩種: 1 YUYV 4:2:2 2 Motion-JPEG 2、V4L2的實現(xiàn)流程一般來說V4L2 采集視頻數(shù)據分為五個步驟:
首先,打開視頻設備文件,進行視頻采集的參數(shù)初始化,通過 V4L2 接口設置視頻圖像的采集窗口、采集的點陣大小和格式;
其次,申請若干視頻采集的幀緩沖區(qū),并將這些幀緩沖區(qū)從內核空間映射到用戶空間,便于應用程序讀取/處理視頻數(shù)據;
第三,將申請到的幀緩沖區(qū)在視頻采集輸入隊列排隊,并啟動視頻采集;
第四,驅動開始視頻數(shù)據的采集,應用程序從視頻采集輸出隊列取出幀緩沖區(qū),處理完后,將幀緩沖區(qū)重新放入視頻采集輸入隊列,循環(huán)往復采 集連續(xù)的視頻數(shù)據;
第五,停止視頻采集。在本次設計中,定義了幾個函數(shù)實現(xiàn)對攝像頭的配置和采集。
一幀圖片采集流程:
圖解過程已經很詳細了,重新總結下。整個過程:
首先:先啟動視頻采集,驅動程序開始采集一幀數(shù)據,把采集的數(shù)據放入視頻采集輸入隊列的第一個幀緩沖區(qū),一幀數(shù)據采集完成,也就是第
一個幀緩沖區(qū)存滿一幀數(shù)據后,驅動程序將該幀緩沖區(qū)移至視頻采集輸出隊列,等待應用程序從輸出隊列取出。驅動程序則繼續(xù)采集下一幀數(shù)據放入第二個緩沖區(qū),同樣幀緩沖區(qū)存滿下一幀數(shù)據后,被放入視頻采集輸出隊列。
然后:應用程序從視頻采集輸出隊列中取出含有視頻數(shù)據的幀緩沖區(qū),處理幀緩沖區(qū)中的視頻數(shù)據,如存儲或壓縮。
最后:應用程序將處理完數(shù)據的幀緩沖區(qū)重新放入視頻采集輸入隊列,這樣可以循環(huán)采集。我們從攝像頭中獲取的視頻幀數(shù)據會放入視頻緩存隊列中,當其他模塊需要處理對應的視頻幀的時候,就會占用緩存塊,也就是這一塊內存被占用,當處理完之后,對應的數(shù)據通過 VO/VENC/VDA 顯示之后,這一緩存塊就沒有用了,可以回收利用?,F(xiàn)在來看,其實海思的底層處理和 linux 的底層處理是一樣的。不過海思本身使用的就是 linux 內核。應該也就是對這一塊進行封裝了而已吧!
海思的公共視頻緩存池按我的理解應該有兩部分,一部分是視頻采集輸入隊列,另一部分是視頻采集輸出隊列,VI 通道是是視頻采集輸出隊列中獲取的視頻幀,而中間 linux 內核的驅動程序會在視頻采集輸入隊列中填充視頻幀,變成視頻輸出隊列。
部分代碼實現(xiàn): 1 /*打開視頻*/ 2 if ((fd = open(FILE_VIDEO, O_RDWR)) == -1) 3 { 4 printf("Error opening V4L interface\n"); 5 return (FALSE); 6 } 7 8 /*讀video_capability中信息。 9 通過調用IOCTL函數(shù)和接口命令VIDIOC_QUERYCAP查詢 10 攝像頭的信息*/ 11 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) 12 { 13 printf("Error opening device %s: unable to query device.\n",FILE_VIDEO); 14 return (FALSE); 15 } 16 else 17 { 18 printf("driver:\t\t%s\n",cap.driver); 19 printf("card:\t\t%s\n",cap.card); 20 printf("bus_info:\t%s\n",cap.bus_info); 21 printf("version:\t%d\n",cap.version); 22 printf("capabilities:\t%x\n",cap.capabilities); 23 24 /*其中capabilities: 4000001通過與各種宏位與, 25 可以獲得物理設備的功能屬性*/ 26 if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE) 27 { 28 printf("Device %s: supports capture.\n",FILE_VIDEO); 29 } 30 31 if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING) 32 { 33 printf("Device %s: supports streaming.\n",FILE_VIDEO); 34 } 35 } //VIDIOC_QUERYCAP對應唯一結構體 3、V4L2測試(640×480像素一幀圖片輸出)我板載上裝的是Logitch c270攝像頭,從攝像頭支持的圖像像素輸出的信息可以看出,在Hi3559板載上可以支持2種像素格式,這里選用的是V4L2_PIX_FMT_YUV422 格式。從生成image的大小可以判斷出是正確的(YUV422數(shù)據大小 = 長 * 寬 * 1.5 = 640 * 480 * 2 = 614400 bytes = 600k)可以將image文件拷出來,使用pYUV 軟件查看YUV圖片。這里需要注意,使用pYUV 查看YUV圖片的時候,需要正確設置圖片格式,按我上面代碼采集的數(shù)據格式,最后一幀圖片輸出結果如下: 之后隨筆將推出結合MPP平臺實現(xiàn)視頻流的輸出。 問題:
在虛擬機上,腳本運行正常,但是會卡在視頻采集處,個人認為是虛擬機的緩存問題,而板載緩存比較充足,所以能夠很好實現(xiàn)。
|
|