V4L2(Video For Linux Two) 是內核提供給應用程序訪問音、視頻驅動的統一接口。html
Linux系統中,視頻設備被看成一個設備文件來看待,設備文件存放在 /dev目錄下,完整路徑的設備文件名爲: /dev/video0 .linux
視頻採集基本步驟流程以下: 打開視頻設備,設置視頻設備屬性及採集方式、視頻數據處理,關閉視頻設備,以下圖所示:web
1、打開視頻設備api
打開視頻設備很是簡單,在V4L2中,視頻設備被看作一個文件。使用open函數打開這個設備:緩存
1. 用非阻塞模式打開攝像頭設備
int cameraFd;
cameraFd = open("/dev/video0", O_RDWR| O_NONBLOCK);數據結構
2. 若是用阻塞模式打開攝像頭設備,上述代碼變爲:
cameraFd = open("/dev/video0", O_RDWR);ide
關於阻塞模式和非阻塞模式函數
應用程序可以使用阻塞模式或非阻塞模式打開視頻設備,若是使用非阻塞模式調用視頻設備,即便還沒有捕獲到信息,驅動依舊會把緩存(DQBUFF)裏的東西返回給應用程序。spa
2、Linux視頻設備驅動經常使用控制命令使用說明.net
設置視頻設備屬性經過ioctl來進行設置,ioctl有三個參數,分別是fd, cmd,和parameter,表示設備描述符,控制命令和控制命令參數。
Linux視頻設備驅動接口V4L2支持的經常使用控制命令以下:
1.控制命令VIDIOC_ENUM_FMT
功能: 獲取當前視頻設備支持的視頻格式 。
參數說明:參數類型爲V4L2的視頻格式描述符類型 struct v4l2_fmtdesc
返回值說明: 執行成功時,函數返回值爲 0;struct v4l2_fmtdesc 結構體中的 .pixelformat和 .description 成員返回當前視頻設備所支持的視頻格式;
使用舉例:
-------------------------------------------------------------------------------------------------
struct v4l2_fmtdescfmt;
memset(&fmt, 0, sizeof(fmt));
fmt.index = 0;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while ((ret = ioctl(dev, VIDIOC_ENUM_FMT,&fmt)) == 0) {
fmt.index++;
printf("{ pixelformat =''%c%c%c%c'', description = ''%s'' }/n",
fmt.pixelformat& 0xFF, (fmt.pixelformat >> 8) & 0xFF,
(fmt.pixelformat>> 16) & 0xFF, (fmt.pixelformat >> 24) & 0xFF,
fmt.description);
}
-------------------------------------------------------------------------------------------------------
2.控制命令VIDIOC_QUERYCAP
功能: 查詢視頻設備的功能 ;
參數說明:參數類型爲V4L2的能力描述類型struct v4l2_capability ;
返回值說明: 執行成功時,函數返回值爲 0;函數執行成功後,struct v4l2_capability 結構體變量中的返回當前視頻設備所支持的功能;例如支持視頻捕獲功能V4L2_CAP_VIDEO_CAPTURE、V4L2_CAP_STREAMING等。
使用舉例:
-------------------------------------------------------------------------------------------------------
structv4l2_capability cap;
iret= ioctl(fd_usbcam, VIDIOC_QUERYCAP, &cap);
if(iret< 0)
{
printf("get vidieo capabilityerror,error code: %d /n", errno);
return ;
}
------------------------------------------------------------------------------------------------------
執行完VIDIOC_QUERYCAP命令後,cap變量中包含了該視頻設備的能力信息,程序中經過檢查cap中的設備能力信息來判斷設備是否支持某項功能。
3.控制命令VIDIOC_S_FMT
功能: 設置視頻設備的視頻數據格式,例如設置視頻圖像數據的長、寬,圖像格式(JPEG、YUYV格式);
參數說明:參數類型爲V4L2的視頻數據格式類型 structv4l2_format ;
返回值說明: 執行成功時,函數返回值爲 0;
使用舉例:
----------------------------------------------------------------------------------------------------------
struct v4l2_format tv4l2_format;
tv4l2_format.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
tv4l2_format.fmt.pix.width =img_width;
tv4l2_format.fmt.pix.height =img_height;
tv4l2_format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
tv4l2_format.fmt.pix.field = V4L2_FIELD_INTERLACED;
iret = ioctl(fd_usbcam, VIDIOC_S_FMT,&tv4l2_format);
-----------------------------------------------------------------------------------------------------------
注意:若是該視頻設備驅動不支持你所設定的圖像格式,視頻驅動會從新修改structv4l2_format結構體變量的值爲該視頻設備所支持的圖像格式,因此在程序設計中,設定完全部的視頻格式後,要獲取實際的視頻格式,要從新讀取struct v4l2_format結構體變量。
4.控制命令VIDIOC_REQBUFS
功能: 請求V4L2驅動分配視頻緩衝區(申請V4L2視頻驅動分配內存),V4L2是視頻設備的驅動層,位於內核空間,因此經過VIDIOC_REQBUFS控制命令字申請的內存位於內核空間,應用程序不能直接訪問,須要經過調用mmap內存映射函數把內核空間內存映射到用戶空間後,應用程序經過訪問用戶空間地址來訪問內核空間。
參數說明:參數類型爲V4L2的申請緩衝區數據結構體類型struct v4l2_requestbuffers ;
返回值說明: 執行成功時,函數返回值爲 0;V4L2驅動層分配好了視頻緩衝區;
使用舉例:
-----------------------------------------------------------------------------------------------------
structv4l2_requestbuffers tV4L2_reqbuf;
memset(&tV4L2_reqbuf, 0, sizeof(struct v4l2_requestbuffers ));
tV4L2_reqbuf.count = 1; //申請緩衝區的個數
tV4L2_reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
tV4L2_reqbuf.memory = V4L2_MEMORY_MMAP;
iret= ioctl(fd_usbcam, VIDIOC_REQBUFS, &tV4L2_reqbuf);
-----------------------------------------------------------------------------------------------------
注意:VIDIOC_REQBUFS會修改tV4L2_reqbuf的count值,tV4L2_reqbuf的count值返回實際申請成功的視頻緩衝區數目;
5.控制命令VIDIOC_QUERYBUF
功能: 查詢已經分配的V4L2的視頻緩衝區的相關信息,包括視頻緩衝區的使用狀態、在內核空間的偏移地址、緩衝區長度等。在應用程序設計中經過調VIDIOC_QUERYBUF來獲取內核空間的視頻緩衝區信息,而後調用函數mmap把內核空間地址映射到用戶空間,這樣應用程序纔可以訪問位於內核空間的視頻緩衝區。
參數說明:參數類型爲V4L2緩衝區數據結構類型 structv4l2_buffer ;
返回值說明: 執行成功時,函數返回值爲 0;struct v4l2_buffer結構體變量中保存了指令的緩衝區的相關信息;
通常狀況下,應用程序中調用VIDIOC_QUERYBUF取得了內核緩衝區信息後,緊接着調用mmap函數把內核空間地址映射到用戶空間,方便用戶空間應用程序的訪問。
使用舉例:
-------------------------------------------------------------------------------------------------------
structv4l2_buffer tV4L2buf;
memset(&tV4L2buf, 0, sizeof(struct v4l2_buffer));
tV4L2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
tV4L2buf.memory = V4L2_MEMORY_MMAP;
tV4L2buf.index = i; // 要獲取內核視頻緩衝區的信息編號
iret = ioctl(fd_usbcam, VIDIOC_QUERYBUF, &tV4L2buf);
// 把內核空間緩衝區映射到用戶空間緩衝區
AppBufLength = tV4L2buf.length;
AppBufStartAddr= mmap(NULL /* start anywhere */ ,
tV4L2buf.length,
PROT_READ | PROT_WRITE/* access privilege */ ,
MAP_SHARED /* recommended */ ,
fd_usbcam, tV4L2buf.m.offset);
-------------------------------------------------------------------------------------------------------
上述代碼在經過調用VIDIOC_QUERYBUF取得內核空間的緩衝區信息後,接着調用mmap函數把內核空間緩衝區映射到用戶空間;關於mmap函數的用法,請讀者查詢相關資料;
6.控制命令VIDIOC_QBUF
功能: 投放一個空的視頻緩衝區到視頻緩衝區輸入隊列中 ;
參數說明:參數類型爲V4L2緩衝區數據結構類型 structv4l2_buffer ;
返回值說明: 執行成功時,函數返回值爲 0;函數執行成功後,指令(指定)的視頻緩衝區進入視頻輸入隊列,在啓動視頻設備拍攝圖像時,相應的視頻數據被保存到視頻輸入隊列相應的視頻緩衝區中。
使用舉例:
-------------------------------------------------------------------------------------------------------
structv4l2_buffer tV4L2buf;
memset(&tV4L2buf, 0, sizeof(struct v4l2_buffer));
tV4L2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
tV4L2buf.memory = V4L2_MEMORY_MMAP;
tV4L2buf.index = i; //指令(指定)要投放到視頻輸入隊列中的內核空間視頻緩衝區的編號;
iret = ioctl(fd_usbcam, VIDIOC_QBUF, &tV4L2buf);
----------------------------------------------------------------------------------------------------
7.控制命令VIDIOC_STREAMON
功能: 啓動視頻採集命令,應用程序調用VIDIOC_STREAMON啓動視頻採集命令後,視頻設備驅動程序開始採集視頻數據,並把採集到的視頻數據保存到視頻驅動的視頻緩衝區中。
參數說明:參數類型爲V4L2的視頻緩衝區類型 enum v4l2_buf_type ;
返回值說明: 執行成功時,函數返回值爲 0;函數執行成功後,視頻設備驅動程序開始採集視頻數據,此時應用程序通常經過調用select函數來判斷一幀視頻數據是否採集完成,當視頻設備驅動完成一幀視頻數據採集並保存到視頻緩衝區中時,select函數返回,應用程序接着能夠讀取視頻數據;不然select函數阻塞直到視頻數據採集完成。Select函數的使用請讀者參考相關資料。
使用舉例:
----------------------------------------------------------------------------------------------------------
enumv4l2_buf_type v4l2type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fd_set fds ;
structtimeval tv;
iret= ioctl(fd_usbcam, VIDIOC_STREAMON, &v4l2type);
FD_ZERO(&fds);
FD_SET(fd_usbcam, &fds);
tv.tv_sec= 2; /* Timeout. */
tv.tv_usec= 0;
iret= select(fd_usbcam+ 1, &fds, NULL, NULL, &tv);
----------------------------------------------------------------------------------------------------------
8.控制命令VIDIOC_DQBUF
功能: 從視頻緩衝區的輸出隊列中取得一個已經保存有一幀視頻數據的視頻緩衝區;
參數說明:參數類型爲V4L2緩衝區數據結構類型 structv4l2_buffer ;
返回值說明: 執行成功時,函數返回值爲 0;函數執行成功後,相應的內核視頻緩衝區中保存有當前拍攝到的視頻數據,應用程序能夠經過訪問用戶空間來讀取該視頻數據。(前面已經經過調用函數mmap作了用戶空間和內核空間的內存映射).
使用舉例:
----------------------------------------------------------------------------------------------------------
structv4l2_buffer tV4L2buf;
memset(&tV4L2buf, 0, sizeof(struct v4l2_buffer));
tV4L2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
tV4L2buf.memory = V4L2_MEMORY_MMAP;
iret= ioctl(fd_usbcam, VIDIOC_DQBUF, &tV4L2buf);
Sasoritattoo註釋:VIDIOC_DQBUF命令結果 使從隊列刪除的緩衝幀信息 傳給了此tVL2buf。V4L2_buffer結構體的做用就至關於申請的緩衝幀的代理,找緩衝幀的都要先問問它,經過它來聯繫緩衝幀,起了中間橋樑的做用。
----------------------------------------------------------------------------------------------------------
9.控制命令VIDIOC_STREAMOFF
功能: 中止視頻採集命令,應用程序調用VIDIOC_ STREAMOFF中止視頻採集命令後,視頻設備驅動程序不在採集視頻數據。
參數說明:參數類型爲V4L2的視頻緩衝區類型 enum v4l2_buf_type ;
返回值說明: 執行成功時,函數返回值爲 0;函數執行成功後,視頻設備中止採集視頻數據。
使用舉例:
----------------------------------------------------------------------------------------------------------
enumv4l2_buf_type v4l2type;
v4l2type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
iret= ioctl(fd_usbcam, VIDIOC_STREAMOFF, &v4l2type);
-----------------------------------------------------------------------------------------------------------
以上就是Linux 視頻設備驅動V4L2最經常使用的控制命令使用說明,經過使用以上控制命令,能夠完成一幅視頻數據的採集過程。
更多控制命令能夠參考v4l2 API :http://linuxtv.org/downloads/v4l-dvb-apis/
v4l2 視頻採集源碼:http://www.cnblogs.com/sj-lv/p/3445056.html
本文轉自:http://blog.csdn.net/Sasoritattoo/article/details/6225486