前言:目前正在忙於arm平台的linux應用程式的開發(其實是剛剛起步學習啦)。底層的東西不用考慮了,開發板子提供了nand bootloader,和linux 2.6的原始碼,而且都編譯好了。自己編譯的bootloader可以用,但是linux編譯後,檔案很大,暫且就用人家編譯的系統,先專心寫應用程式 吧。。
下面具體說明開發流程(網上找的啦,也在學習麼)
// 用非阻塞模式開啟攝像頭裝置
int camerafd;
camerafd = open(「/dev/video0″, o_rdwr | o_nonblock, 0);
// 如果用阻塞模式開啟攝像頭裝置,上述**變為:
//camerafd = open(」/dev/video0″, o_rdwr, 0);
關於阻塞模式和非阻塞模式
設定屬性及採集方式
extern int ioctl (int __fd, unsigned long int __request, …) __throw;
__request:具體的命令標誌符。
在進行v4l2開發中,一般會用到以下的命令標誌符:
vidioc_reqbufs:分配記憶體
vidioc_querycap:查詢驅動功能
vidioc_s_fmt:設定當前驅動的頻捕獲格式
vidioc_g_fmt:讀取當前驅動的頻捕獲格式
vidioc_try_fmt:驗證當前驅動的顯示格式
vidioc_cropcap:查詢驅動的修剪能力
vidioc_qbuf:把資料從快取中讀取出來
vidioc_dqbuf:把資料放回快取佇列
這些io呼叫,有些是必須的,有些是可選擇的。
在亞洲,一般使用pal(720x576)制式的攝像頭,而歐洲一般使用ntsc(720x480),使用vidioc_querystd來檢測:
v4l2_std_id std;
do while (ret == -1 && errno == eagain);
switch (std)
struct v4l2_format fmt;
memset ( &fmt, 0, sizeof(fmt) );
fmt.type = v4l2_buf_type_video_capture;
fmt.fmt.pix.width = 720;
fmt.fmt.pix.height = 576;
fmt.fmt.pix.pixelformat = v4l2_pix_fmt_yuyv;
fmt.fmt.pix.field = v4l2_field_interlaced;
if (ioctl(fd, vidioc_s_fmt, &fmt) == -1)
v4l2_format結構體定義如下:
struct v4l2_format
fmt;
};struct v4l2_pix_format
;分配記憶體
struct v4l2_requestbuffers req;
if (ioctl(fd, vidioc_reqbufs, &req) == -1)
v4l2_requestbuffers定義如下:
struct v4l2_requestbuffers
;獲取並記錄快取的物理空間
使用vidioc_reqbufs,我們獲取了req.count個快取,下一步通過呼叫vidioc_querybuf命令來獲取這些快取的位址,然後使用mmap函式轉換成應用程式中的絕對位址,最後把這段快取放入快取佇列:
typedef struct videobuffer videobuffer;
videobuffer* buffers = calloc( req.count, sizeof(*buffers) );
struct v4l2_buffer buf;
for (numbufs = 0; numbufs < req.count; numbufs++)
buffers[numbufs].length = buf.length;
// 轉換成相對位址
buffers[numbufs].start = mmap(null, buf.length,
prot_read | prot_write,
map_shared,
fd, buf.m.offset);
if (buffers[numbufs].start == map_failed)
// 放入快取佇列
if (ioctl(fd, vidioc_qbuf, &buf) == -1) }
作業系統一般把系統使用的記憶體劃分成使用者空間和核心空間,分別由應用程式管理和作業系統管理。應用程式可以直接訪問記憶體的位址,而核心空間存放的是 供核心訪問的**和資料,使用者不能直接訪問。v4l2捕獲的資料,最初是存放在核心空間的,這意味著使用者不能直接訪問該段記憶體,必須通過某些手段來轉換地 址。
read、write方式:在使用者空間和核心空間不斷拷貝資料,占用了大量使用者記憶體空間,效率不高。
記憶體對映方式:把裝置裡的記憶體對映到應用程式中的記憶體控制項,直接處理裝置記憶體,這是一種有效的方式。上面的mmap函式就是使用這種方式。
使用者指標模式:記憶體片段由應用程式自己分配。這點需要在v4l2_requestbuffers裡將memory欄位設定成v4l2_memory_userptr。
處理採集資料
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type=v4l2_buf_type_video_capture;
buf.memory=v4l2_memory_mmap;
buf.index=0;
//讀取快取
if (ioctl(camerafd, vidioc_dqbuf, &buf) == -1)
//重新放入快取佇列
if (ioctl(camerafd, vidioc_qbuf, &buf) == -1)
close(camerafd)
還需要使用munmap方法。
附錄:標準的v4l2的api
Linux V4L2 原始碼分析
video for linux 2真的是乙個很複雜的框架,抽象倒不是它複雜的原因,是因為耦合了其他框架的內容,導致要掌握v4l2必須得需要乙個非常廣的核心層知識面,以及linux抽象思想。這篇文章將會以ov2640.c為例子進行原始碼分析,我會盡量從上往下,也就是使用者層呼叫到核心層進行分析。注 在...
V4L2程式設計
include include include include include include include include include include typedef struct buftype buftype user buf int n buffer 0 開啟攝像頭裝置 int ope...
V4L2 程式設計
v4l2程式設計 1.定義 2.工作流程 開啟裝置 檢查和設定裝置屬性 設定幀格式 設定一種輸入輸出方法 緩衝區管理 迴圈獲取資料 關閉裝置。3.裝置的開啟和關閉 include int open const char device name,int flags include int close ...