午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

Hi3559AV100外接UVC/MJPEG相機實時采圖設計(二):V4L2接口的實現(xiàn)(以YUV422為例)

 悅光陰 2022-01-20

  下面將給出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)對攝像頭的配置和采集。
一幀圖片采集流程:


 動態(tài)視頻采集流程:

 

  圖解過程已經很詳細了,重新總結下。整個過程:
  首先:先啟動視頻采集,驅動程序開始采集一幀數(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)。

 

 

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多