1. 程式人生 > >攝像頭驅動(一)————V4L2框架淺析

攝像頭驅動(一)————V4L2框架淺析

V4L2 :video for linux version 2 ,是 linux 裡一套標準的視訊驅動,它支援 uvc 標準的攝像頭。本文來分析一下它的核心框架。


  整個v4l2的框架分為三層:

    在應用層,我們可以在 /dev 目錄發現 video0 類似的裝置節點,上層的攝像頭程式開啟裝置節點進行資料捕獲,顯示視訊畫面。裝置節點的名字很統一,video0 video1 video2...這些裝置節點在是核心層註冊。

    核心層 v4l2-dev.c,承上啟下,對於每一個硬體相關層註冊進來的裝置,設定一個統一的介面 v4l2_fops ,既然是統一的介面必然不是具體的視訊裝置的操作函式,應用層呼叫 v4l2_fops 中的函式最終將呼叫到硬體相關層的 video_device 的 fops 。

    硬體相關層,與具體的視訊硬體打交道,分配、設定、註冊 video_device 結構體。

[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. staticint __init videodev_init(void)  
  2. {  
  3.     /* 申請裝置號,留給 video 裝置使用 */
  4.     dev_t dev = MKDEV(VIDEO_MAJOR, 0);  
  5.     ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME);  
  6.     /* 建立 video 類 */
  7.     ret = class_register(&video_class);  
  8.     return 0;  
  9. }  
[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. struct video_device  
  2. {  
  3.     /* device ops */
  4.     conststruct v4l2_file_operations *fops;  
  5.     /* sysfs */
  6.     struct device dev;      /* v4l device */
  7.     struct cdev *cdev;      /* character device */
  8.     /* Set either parent or v4l2_dev if your driver uses v4l2_device */
  9.     struct device *parent;          /* device parent */
  10.     struct v4l2_device *v4l2_dev;   /* v4l2_device parent */
  11.     /* Control handler associated with this device node. May be NULL. */
  12.     struct v4l2_ctrl_handler *ctrl_handler;  
  13.     /* Priority state. If NULL, then v4l2_dev->prio will be used. */
  14.     struct v4l2_prio_state *prio;  
  15.     /* device info */
  16.     char name[32];  
  17.     int vfl_type;  
  18.     /* 'minor' is set to -1 if the registration failed */
  19.     int minor;  
  20.     u16 num;  
  21.     /* use bitops to set/clear/test flags */
  22.     unsigned long flags;  
  23.     /* attribute to differentiate multiple indices on one physical device */
  24.     int index;  
  25.     /* V4L2 file handles */
  26.     spinlock_t      fh_lock; /* Lock for all v4l2_fhs */
  27.     struct list_head    fh_list; /* List of struct v4l2_fh */
  28.     int debug;          /* Activates debug level*/
  29.     /* Video standard vars */
  30.     v4l2_std_id tvnorms;        /* Supported tv norms */
  31.     v4l2_std_id current_norm;   /* Current tvnorm */
  32.     /* callbacks */
  33.     void (*release)(struct video_device *vdev);  
  34.     /* ioctl callbacks */
  35.     conststruct v4l2_ioctl_ops *ioctl_ops;  
  36.     DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);  
  37.     /* serialization lock */
  38.     DECLARE_BITMAP(disable_locking, BASE_VIDIOC_PRIVATE);  
  39.     struct mutex *lock;  
  40. };  
[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. struct v4l2_device {  
  2.     struct device *dev;  
  3.     /* used to keep track of the registered subdevs */
  4.     struct list_head subdevs;  
  5.     spinlock_t lock;  
  6.     char name[V4L2_DEVICE_NAME_SIZE];  
  7.     void (*notify)(struct v4l2_subdev *sd, unsigned int notification, void *arg);  
  8.     struct v4l2_ctrl_handler *ctrl_handler;  
  9.     struct v4l2_prio_state prio;  
  10.     struct mutex ioctl_lock;  
  11.     struct kref ref;  
  12.     void (*release)(struct v4l2_device *v4l2_dev);  
  13. };  
[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. staticinlineint __must_check video_register_device(struct video_device *vdev,  
  2.         int type, int nr)  
  3. {  
  4.     return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);  
  5. }  
  6. int __video_register_device(struct video_device *vdev, int type, int nr,  
  7.         int warn_if_nr_in_use, struct module *owner)  
  8. {  
  9.     int i = 0;  
  10.     int ret;  
  11.     int minor_offset = 0;  
  12.     int minor_cnt = VIDEO_NUM_DEVICES;  
  13.     constchar *name_base;  
  14.     /* A minor value of -1 marks this video device as never having been registered */
  15.     vdev->minor = -1;  
  16.     /* 視訊裝置的裝置節點一般為 video0 ..video 就是由此而來 */
  17.     switch (type) {  
  18.     case VFL_TYPE_GRABBER:  
  19.         name_base = "video";  
  20.         break;  
  21.     case VFL_TYPE_VBI:  
  22.         name_base = "vbi";  
  23.         break;  
  24.     ...  
  25.     }  
  26.     vdev->vfl_type = type;  
  27.     vdev->cdev = NULL;  
  28.     /* Part 2: find a free minor, device node number and device index. */
  29. #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
  30.     switch (type) {  
  31.     case VFL_TYPE_GRABBER:  
  32.         minor_offset = 0;  
  33.         minor_cnt = 64;  
  34.         break;  
  35.     ...  
  36. #endif
  37.     /* 尋找一個空的項,這個好像並不重要 */
  38.     mutex_lock(&videodev_lock);  
  39.     nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);  
  40.     if (nr == minor_cnt)  
  41.         nr = devnode_find(vdev, 0, minor_cnt);  
  42.     if (nr == minor_cnt) {  
  43.         printk(KERN_ERR "could not get a free device node number\n");  
  44.         mutex_unlock(&videodev_lock);  
  45.         return -ENFILE;  
  46.     }  
  47. #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
  48.     /* 1-on-1 mapping of device node number to minor number */
  49.     i = nr;  
  50. #else
  51.     /* 在全域性 video_deivce 陣列中尋找一個空的項,下標+minor_offset作為裝置的次裝置號 */
  52.     for (i = 0; i < VIDEO_NUM_DEVICES; i++)  
  53.         if (video_device[i] == NULL)  
  54.             break;  
  55.     if (i == VIDEO_NUM_DEVICES) {  
  56.         mutex_unlock(&videodev_lock);  
  57.         printk(KERN_ERR "could not get a free minor\n");  
  58.         return -ENFILE;  
  59.     }  
  60. #endif
  61.     vdev->minor = i + minor_offset;  
  62.     vdev->num = nr;  
  63.     devnode_set(vdev);  
  64.     if (vdev->ioctl_ops)  
  65.         determine_valid_ioctls(vdev);  
  66.     /* 註冊字元裝置 */
  67.     vdev->cdev = cdev_alloc();  
  68.     vdev->cdev->ops = &v4l2_fops;  
  69.     vdev->cdev->owner = owner;  
  70.     ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);  
  71.     /* 得把device註冊進核心,mdev才能自動建立裝置節點,/dev 目錄下的video0 等就是來自這裡 */
  72.     vdev->dev.class = &video_class;  
  73.     vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);  
  74.     if (vdev->parent)  
  75.         vdev->dev.parent = vdev->parent;  
  76.     dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);  
  77.     ret = device_register(&vdev->dev);  
  78.     vdev->dev.release = v4l2_device_release;  
  79.     /* Part 6: Activate this minor. The char device can now be used. */
  80.     set_bit(V4L2_FL_REGISTERED, &vdev->flags);  
  81.     mutex_lock(&videodev_lock);  
  82.     video_device[vdev->minor] = vdev;  
  83.     mutex_unlock(&videodev_lock);  
  84.     return 0;  
  85. }  
  86. EXPORT_SYMBOL(__video_register_device);  
[cpp] view plain copy  print?在CODE上檢視程式碼片派生到我的程式碼片
  1. staticconststruct file_operations v4l2_fops = {  
  2.     .owner = THIS_MODULE,  
  3.     .read = v4l2_read,  
  4.     .write = v4l2_write,  
  5.     .open = v4l2_open,  
  6.     .get_unmapped_area = v4l2_get_unmapped_area,  
  7.     .mmap = v4l2_mmap,  
  8.     .unlocked_ioctl = v4l2_ioctl,  
  9. #ifdef CONFIG_COMPAT
  10.     .compat_ioctl = v4l2_compat_ioctl32,  
  11. #endif
  12.     .release = v4l2_release,  
  13.     .poll = v4l2_poll,  
  14.     .llseek = no_llseek,  
  15. };  
[cpp] view plain copy  

相關推薦

攝像頭驅動————V4L2框架淺析

V4L2 :video for linux version 2 ,是 linux 裡一套標準的視訊驅動,它支援 uvc 標準的攝像頭。本文來分析一下它的核心框架。   整個v4l2的框架分為三層:     在應用層,我們可以在 /dev 目錄發現 video0 類

攝像頭驅動————V4L2 虛擬攝像頭驅動vivi深入分析

本文基於:linux3.5   前面一篇文章中,簡單分析了 V4L2 大框架,本文藉助核心中的虛擬攝像頭驅動 vivi 來分析一個完整的攝像頭驅動程式。vivi 相對於後面要分析的 usb 攝像頭驅動程式,它沒有真正的硬體相關層的操作,也就是說拋開了複雜的 us

V4L2攝像頭測試

利用VIDIOC_G_CTRL得到一些設定: 一些具體的設定,如曝光模式(Exposure Type),曝光值(Exposure),增益(Gain),白平衡(WHITE_BALANCE),亮度(BRIGHTNESS),飽和度(SATURATION),對比度(CONTRAST)等資訊。

OpenGL在MFC中的使用總結——基本框架

palette 接受 white 要求 無效 結構 del 一次 是你 項目中要畫3D顯示的模型,於是要用到OpenGL,加上是在MFC中,並且是在MFC中的ActiveX中使用。再並且鑒於他們程序主框架的設定。常規的方法還不一定能實現。所以還是查過不少資料,在此一一總

python selenium系列框架介紹及安裝

row pre ive AS baidu mar 在操作 pan 但是 一 selenium是什麽?引用百度百科的介紹selenium的一段話:“Selenium 是一個用於Web應用程序測試的工具。Selenium測試直接運行在瀏覽器中,就像真正的用戶在操作一樣。支持的

Scrapy框架學習Scrapy框架介紹

Scrapy框架的架構圖如上。 Scrapy中的資料流由引擎控制,資料流的過程如下: 1.Engine開啟一個網站,找到處理該網站的Sprider,並向該Sprider請求第一個要爬取得URL。 2.Engine從Sprider中獲取到第一個要爬的URL,並通過Scheduler以Requ

flask框架使用教程系列——準備環境

一、安裝Python2.7(python3.6同理) Mac 下使用Python2.7 Windows下使用Python2.7 2.1 從Python 官網下載Python2.7的版本; 2.2 雙擊Python2.7,然後選擇安裝路徑,全部下一步安裝就可以了; 2.

crm銷售管理系統SSM框架搭建

前言:ssm框架是spring+springMvc+Mybatis的縮寫,是繼SSH框架後又一個主流的java EE企業級框架,適用於搭建各種大型的企業級應用系統。這不,我所在公司的產品也是基於該主流框架進行搭建的。初識SSM框架是各種的不適應,不過使用久了發現ssm框架異常順手。使用幾個月下來可以說在開發公

GAN:基本框架

GAN(一):基本框架 一、GAN的概念 二、algorithm 小白的第一篇部落格,寫的有不對的地方,望各位批評指正; 一、GAN的概念 1)generator:Neural Network image generation: 給定一個

微信小程式學習筆記框架及工具

文章目錄 一、app.json的配置 1. 決定頁面檔案路徑 2. 配置視窗表現 3. 配置tab標籤導航 4. 設定網路超時時間 5. 配置debug模式 二、App()函式使用

SSH框架學習——匯入框架所需jar包

SSH框架學習(一)——匯入框架所需jar包 一、建立一個web專案 二、匯入Struts2的jar包 三、匯入Hibernate的jar包 四、匯入Spring的jar包 IOC開發: AOP開發: 五、引入整合

電商大資料分析平臺專案專案框架

開發可以在web專案中內嵌的js sdk。每當使用者瀏覽到網站頁面或者觸發某種事件時,會呼叫js程式碼,根據使用者cookie傳送一個session資訊這時到我們的nginx伺服器中。 nginx伺服器在接收到傳送的session後會將其寫入日誌檔案中記錄下來,這時監聽日誌檔案的flume會將session

Spring框架學習之路——Spring框架基本介紹

Spring的出現是為了取代EJB(Enterprise JavaBean)的臃腫、低效、脫離現實的缺點。Spring致力於J2EE應用的各層(表現層、業務層、持久層)的解決方案,Spring是企業應用開發的“一站式”選擇。 1.Spring定義: Spring是分層的J

深入理解PlasmaPlasma 框架

這一系列文章將圍繞以太坊的二層擴容框架,介紹其基本執行原理,具體操作細節,安全性討論以及未來研究方向等。本篇文章作為開篇,主要目的是理解 Plasma 框架。 Plasma 作為以太坊的二層擴容框架,自從 2017 年被 Joseph Poon(Lightnin

springboot視訊教程系列SpringBoot框架初相識-王勇-專題視訊課程

springboot視訊教程系列(一)SpringBoot框架初相識—126人已學習 課程介紹         本章主要介紹什麼是SpringBoot框架?SpringBoot開發框架的主要特性以及

UE4移動元件詳解——移動框架與實現原理

前言 關於UE4的移動元件,我寫了一篇非常詳細的分析文件。由於篇幅比較大,我將其拆分成三個部分。分別從移動框架與實現原理,移動的網路同步,移動元件的優化與改造三個方面來寫。這三篇文件中難免有問題和漏洞,所以我也會在發現問題時及時更新和修改,也希望大家能給出一些

vue從入門到女裝??:從零開始搭建後臺管理系統安裝框架

安裝及執行都是基於node的,不會node的可以自行百度,網上教程很多,也不難 專案效果預覽: demo1 demo2 原始碼下載 開始安裝框架: vue element-ui   注意如果報錯安裝失敗就重新安裝,不然雖然本地有element的依賴包但是可能會出一些奇怪的錯誤 另外element-ui

Linux塊裝置驅動————塊裝置的結構及磁碟的結構

塊裝置的結構及磁碟的結構 1、扇區 磁碟上的每個磁軌被等分成若干個弧段,這些弧段便是磁碟的扇區。磁碟驅動器在向磁碟讀寫資料時,都是以扇區為單位。一般為512個位元組,但也有1024或者

Spring 註解驅動基本使用規則

Spring 註解驅動(一)基本使用規則 Spring 系列目錄(https://www.cnblogs.com/binarylei/p/10198698.html) 一、基本使用 @Configuration @ComponentScan(basePackages = "com.github.bina

步教你構建一個MPU6050I2C類驅動

1 i2c基本協議和時序 i2c基礎的知識這裡就不提了,直接從時序開始,直接來看看i2c的波形 2 i2c子系統軟體框架 先來看看i2c匯流排的分層思想: 在分層圖中我們可以看到,driver和device在核心層中分別成為了2條連結串列,核心層會按一定的