2023年12月2日Linux開發手記

2021-10-01 05:20:44 字數 4780 閱讀 1179

知識準備:

2.獲得裝置資訊。

3.根據需要更改裝置的相關設定。

4.獲得採集到的影象資料(在這裡v4l提供了兩種方式,直接通過開啟的裝置讀取資料,使用mmap記憶體對映的方式獲取資料)。

5.對採集到的資料進行操作(如顯示到螢幕,影象處理,儲存成檔案)。

知道了流程之後,我們就需要根據流程完成相應的函式。

第一步:

具體的函式如下

#define default_device 「/dev/video0」

int v4l_open(char *dev , v4l_device *vd)

if(!dev)dev= default_device;

if((vd-fd=open(dev,o_rdwr))<0)

if(v4l_get_capability(vd))return -1;

if(v4l_get_picture(vd))return -1;//這兩個函式就是即將要完成的獲取裝置資訊的函式

return 0

同樣對於第6步也十分簡單,就是int v4l_close(v4l_device *);的作用。

函式如下:

int v4l_close(v4l_device *vd)

第二步:

現在我們完成第2步中獲得裝置資訊的任務,下面先給出函式在對函式作出相應的說明。

int v4l_get_capability(v4l_device *vd)

if (ioctl(vd->fd, vidiocgcap, &(vd->capability)) < 0) picture結構包括了亮度,對比度,色深,調色盤等等資訊。標頭檔案裡還列出了palette相關的值,這裡並沒有給出。

這裡直接給出另外乙個函式

int v4l_get_mbuf(v4l_device *vd)  

if (ioctl(vd->fd, vidiocgmbug ,&(vd->mbuf)) < 0)   

return 0;

上述函式就是更改picture相關屬性的例子,其核心還是v4l給我們提供的ioctl的相關呼叫,通過這個函式可以修改如亮度,對比度等相關的值。

第4步獲得採集到的影象資料。

這一步是使用v4l比較重要的一步,涉及到幾個函式的編寫。當然使用v4l就是為了要獲得影象,所以這一步很關鍵,但是當你獲得了影象資料後,還需要根據你想要達到的目的和具體情況做進一步的處理,也就是第5步所做的事情,這些內容將在後面第三部分提到。這裡講如何獲得採集到的資料。

如前所述獲得影象的方式有兩種,分別是直接讀取裝置和使用mmap記憶體對映,而通常大家使用的方法都是後者。

1).直接讀取裝置

直接讀裝置的方式就是使用read()函式,我們先前定義的

extern int v4l_grab_picture(v4l_device *, unsigned int);函式就是完成這個工作的,它的實現也很簡單。

int v4l_grab_picture(v4l_device *vd, unsighed int size)

if(read(vd-fd,&(vd->map),size)==0)return -1;

return 0;

該函式的使用也很簡單,就是給出影象資料的大小,vd->map所指向的資料就是影象資料。而影象資料的大小你要根據裝置的屬性自己計算獲得。

2).使用mmap記憶體對映來獲取影象

在這部分涉及到下面幾個函式,它們配合來完成最終影象採集的功能。

extern int v4l_mmap_init(v4l_device *);該函式把攝像頭影象資料對映到程序記憶體中,也就是只要使用vd->map指標就可以使用採集到的影象資料(下文詳細說明)

extern int v4l_grab_init(v4l_device *, int, int);該函式完成影象採集前的初始化工作。

extern int v4l_grab_frame(v4l_device *, int);該函式是真正完成影象採集的一步,在本文使用了乙個通常都會使用的乙個小技巧,可以在處理一幀資料時同時採集下一幀的資料,因為通常我們使用的攝像頭都可以至少儲存兩幀的資料。

extern int v4l_grab_sync(v4l_device *);該函式用來完成擷取影象的同步工作,在擷取一幀影象後呼叫,返回表明一幀擷取結束。

下面分別介紹這幾個函式。

mmap()系統呼叫使得程序之間通過對映同乙個普通檔案實現共享記憶體。普通檔案被對映到程序位址空間後,程序可以像訪問普通記憶體一樣對檔案進行訪問,不必在呼叫read(),write()等操作。兩個不同程序a、b共享記憶體的意思是,同一塊物理記憶體被對映到程序a、b各自的程序位址空間。程序a可以即時訪問程序b對共享記憶體中資料的更新,反之亦然。

採用共享記憶體通訊的乙個顯而易見的好處是減少i/o操作提高讀取效率,因為使用mmap後程序可以直接讀取記憶體而不需要任何資料的拷貝。

mmap的函式原型如下

void* mmap ( void * addr , size_t len , int prot , int flags , int fd , off_t offset )

len:指定對映記憶體的大小。在我們這裡,該值為攝像頭mbuf結構體的size值,即影象資料的總大小。

port:指定共享記憶體的訪問許可權 prot_read(可讀),prot_write(可寫)

flags:一般設定為map_shared

fd:同享檔案的檔案描述符。

介紹完了mmap的使用,就可以介紹上文中定義的函式extern int v4l_mmap_init(v4l_device *);了。先給出這個函式的**,再做說明。

int v4l_mmap_init(v4l_device *vd)  

if (v4l_get_mbuf(vd) < 0)  

return -1;  

if ((vd->map = mmap(0, vd->mbuf.size, prot_read|prot_write, map_shared, vd->fd, 0)) < 0) {  

perror("v4l_mmap_init:mmap");  

return -1;  

return 0;  

這個函式首先使用v4l_get_mbuf(vd)獲得乙個攝像頭重要的引數,就是需要對映記憶體的大小,即vd->mbuf.size,然後呼叫mmap,當我們在程式設計是呼叫v4l_mmap_init後,vd.map指標所指向的記憶體空間即為我們將要採集的影象資料。

獲得影象前的初始化工作v4l_grab_init();該函式十分簡單直接粘上去,其中將。vd->frame_using[0]和vd->frame_using[1]都設為false,表示兩幀的擷取都沒有開始。

int v4l_grab_init(v4l_device *vd, int width, int height)  

vd->mmap.width = width;   

vd->mmap.height = height;   

vd->mmap.format = vd->picture.palette;   

vd->frame_current = 0;  

vd->frame_using[0] = false;  

vd->frame_using[1] = false;  

return v4l_grab_frame(vd, 0);  

真正獲得影象的函式extern int v4l_grab_frame(v4l_device *, int);

int v4l_grab_frame(v4l_device *vd, int frame)  

if (vd->frame_using[frame]) {  

fprintf(stderr, "v4l_grab_frame: frame %d is already used./n", frame);  

return -1;  

vd->mmap.frame = frame;  

if (ioctl(vd->fd, vidiocmcapture, &(vd->mmap)) < 0) {  

perror("v4l_grab_frame");  

return -1;  

vd->frame_using[frame] = true;  

vd->frame_current = frame;  

return 0;  

讀到這裡,應該覺得這個函式也是相當的簡單。最關鍵的一步即為呼叫ioctl(vd->fd, vidiocmcapture, &(vd->mmap)),呼叫後相應的影象就已經獲取完畢。其他的**是為了完成雙緩衝就是擷取兩幀影象用的,可以自己理解下。

在擷取影象後還要進行同步操作,就是呼叫extern int v4l_grab_sync(v4l_device *);函式,該函式如下

int v4l_grab_sync(v4l_device *vd)  

if (ioctl(vd->fd, vidiocsync, &(vd->frame_current)) < 0) {  

perror("v4l_grab_sync");  

vd->frame_using[vd->frame_current] = false;  

return 0;  

該函式返回0說明你想要獲取的影象幀已經獲取完畢。

影象存在了**?

最終我們使用v4l的目的是為了獲取裝置中的影象,那麼影象存在**?從上面的文章可以知道,vd.map指標所指就是你要獲得的第一幀影象。影象的位置,存在vd.map+vd.mbuf.offsets[vd.frame_current]處。其中vd.frame_current=0,即為第一幀的位置,vd.frame_current=1,為第二幀的位置

2023年12月12日總結

今天用plsql進行pde檔案匯入時,提示表空間不存在,有兩個伺服器,從a伺服器匯出的pde檔案在b伺服器匯入表,在plsql選擇工具 匯入表,在pl sql developer標籤下的在建立表前打鉤,然後匯入檔案那選擇剛才匯出生成的pde檔案,按匯入,結果出錯,日誌如下 import starte...

2023年12月4日Linux開發手記

ok,經過昨天對v4l2工作流程的學習,現在已經大體了解了v4l2的工作原理,現在開始對v4l2的api的學習,目標 1 開啟攝像頭 2 儲存影象 3 關閉攝像頭,api linux media infrastructure userspace api the linux kernel docume...

2023年12月1日Linux開發手記

配置ubuntu攝像頭 1 設定 新增 usb控制器 相容usb3.0 2 虛擬機器 可移動裝置 web camera 連線 斷開主機 3 檢視是否配置成功,開啟終端,輸入 susb ls dev video 輸出 dev video0 配置成功 4 開啟ubuntu自帶的chesse軟體 茄子 執...