Linux中V4L2分析


一、vivi.c分析

1、vivi.c是Linux中虛擬的v4l2驅動,使用它來學習v4l2驅動架構

 1.vivi驅動涉及文件:

            vivi.c                        驅動的具體實現

            v4l2-common.c

            V4L2-dev.c            video_register_device(struct video_device *vdev...);

            V4L2-device.c       v4l2_device_register(struct device *dev,struct v4l2_device *v4l2_device);

            videobuf_core.c

            videobuf_vmalloc.c

2.主要關注以下幾個結構體:

             struct video_device   視頻類設備的基類,另外字符設備驅動的基類為cdev,所有的操作都是圍繞cdev結構體

             struct v4l2_file_operations   包含vivi_read,vivi_open等函數具體實現。在系統調用的時候,會首先調用cdev的file_operations的v4l2_read,v4l2_open等函數,在這些函數中會使用struct file中的video_device來調用vivi_read等函數具體去實現。

             struct v4l2_ioctl_ops            ioctl操作的函數的具體實現

             struct V4l2_device

             struct videobuf_buffer           視頻數據緩沖區,對應一幀視頻,里面包含視頻的大小等信息

             struct videobuf_queue          視頻緩沖區隊列

        以上幾個結構體可能不會被單獨使用,一般都被包含在某個更大的對象結構中,比如video_device和v4l2_device都包含在vivi_dev中,而vivi_dev被包含在viv_fh中,videobuf_buffer被包含在vivi_buffer中。

這個struct file_opertions v4l2_fops是字符設備給上層提供的系統調用,這里的函數最終調用的還是struct v4l2_file_operations (vivi_fops)的實現,可以查看v4l2_open的實現。videobuf_queue_ops中實現了緩沖隊列的一些操作,buffer_setup,buffer_prepare,buffer_queue,buffer_release等,但是這些申請的緩沖隊列都是在內核空間,在vivi_mmap函數中videobuf_mmap_mapper(struct videobuf_queue *q,struct vm_area_struct *vma);將緩沖隊列映射到vm_area_struct虛擬地址

3.分析程序流程:

在vivi.c文件中

vivi_create_instance()

      v4l2_device_register()

      給video_device vdev對象賦值v4l2_file_operations和v4l2_ioctl_ops等

      video_device_register()

          初始化video_device對象vdev

          初始化video_device中的cdev結構體

                      cdev_add()注冊字符設備

          初始化video_device中struct device結構體

                     device_register()在/dev/目錄下創建設備節點

  v4l2_dev.c文件里file_operations中的v4l2_ioctl最終調用的還是vivi.c文件里v4l2_file_operations中的video_ioctl2函數,但是這里的video_ioctl2不像vivi_open,vivi_read等是具體的實現,video_ioctl2具體的實現已經單獨拿出來放到v4l2_ioctl.c文件中了,所以video_ioctl2最終調用的是v4l2_ioctl.c文件中的__video_do_ioctl(file,cmd,arg)函數,而__video_do_ioctl(file,cmd,arg)函數又回過來調用vivi_ioctl中vivi_ioctl_ops中的函數。

 

 二、V4L2架構分析

  v4l2向上為應用程序提供了統一的調用接口,向下為設備驅動程序提供了統一的V4L2框架;Linux中V4L2驅動的視頻設備(如攝像頭、視頻采集卡)的設備文件為/dev/videoX,主設備號81,對於視頻設備次設備號為0-63(是字符設備),Radio設備為64-127,Teltext設備為192-223,VBI設備是224-255,V4L2驅動的視頻設備在用戶空間通過ioctl()控制,還可以進行mmap()映射。

要想了解 V4l2 有幾個重要的文檔是必須要讀的:

1、源碼Documentation/video4linux目錄下的V4L2-framework.txtvideobuf

2、V4L2的官方API文檔V4L2 API Specification

3、源碼drivers/media/video目錄下的sample程序vivi.c(虛擬視頻驅動程序,此代碼模擬一個真正的視頻設備V4L2 API)。

V4l2可以支持多種設備,它可以有以下幾種接口:

1. 視頻采集接口(video capture interface):這種應用的設備可以是高頻頭或者攝像頭.V4L2的最初設計就是應用於這種功能的.

2. 視頻輸出接口(video output interface):可以驅動計算機的外圍視頻圖像設備--像可以輸出電視信號格式的設備.

3. 直接傳輸視頻接口(video overlay interface):它的主要工作是把從視頻采集設備采集過來的信號直接輸出到輸出設備之上,而不用經過系統的CPU.

4. 視頻間隔消隱信號接口(VBI interface):它可以使應用可以訪問傳輸消隱期的視頻信號.

5. 收音機接口(radio interface):可用來處理從AM或FM高頻頭設備接收來的音頻流.

 

V4L2 驅動核心

V4L2 的驅動源碼在drivers/media/video目錄下,主要核心代碼有:

v4l2-dev.c                  //linux版本2視頻捕捉接口,主要結構體 video_device 的注冊
v4l2-common.c               //在Linux操作系統體系采用低級別的操作一套設備structures/vectors的通用視頻設備接口。
                            //此文件將替換videodev.c的文件配備常規的內核分配。
v4l2-device.c               //V4L2的設備支持。注冊v4l2_device
v4l22-ioctl.c               //處理V4L2的ioctl命令的一個通用的框架。
v4l2-subdev.c               //v4l2子設備
v4l2-mem2mem.c              //內存到內存為Linux和videobuf視頻設備的框架。設備的輔助函數,使用其源和目的地videobuf緩沖區。

頭文件linux/videodev2.h、media/v4l2-common.h、media/v4l2-device.h、media/v4l2-ioctl.h、media/v4l2-dev.h、media/v4l2-ioctl.h等。

 來源:http://zjbintsystem.blog.51cto.com/964211/464729       http://www.rosoo.net/a/201001/8382.html   (此二者類似)

Video4linux2一般操作流程(視頻設備):
1. 打開設備文件。 int fd=open(”/dev/video0″,O_RDWR);
2. 取得設備的capability,看看設備具有什么功能,比如是否具有視頻輸入等。VIDIOC_QUERYCAP,struct v4l2_capability
3. 選擇視頻輸入,一個視頻設備可以有多個視頻輸入。VIDIOC_S_INPUT,struct v4l2_input
4. 設置視頻的制式和幀格式,制式包括PAL,NTSC,幀的格式個包括寬度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
5. 向驅動申請幀緩沖,一般不超過5個。struct v4l2_requestbuffers
6. 將申請到的幀緩沖映射到用戶空間,這樣就可以直接操作采集到的幀了,而不必去復制。
7. 將申請到的幀緩沖全部入隊列,以便存放采集到的數據.VIDIOC_QBUF,struct v4l2_buffer
8. 開始視頻的采集。VIDIOC_STREAMON
9. 出隊列以取得已采集數據的幀緩沖,取得原始采集數據。VIDIOC_DQBUF
10. 將緩沖重新入隊列尾,這樣可以循環采集。VIDIOC_QBUF
11. 停止視頻的采集。VIDIOC_STREAMOFF
12. 關閉視頻設備。close(fd);
常用的結構體(參見linux-2.6.18_pro500/include/linux/include/linux/videodev2.h):
struct v4l2_requestbuffers reqbufs;//向驅動申請幀緩沖的請求,里面包含申請的個數
struct v4l2_capability cap;//這個設備的功能,比如是否是視頻輸入設備
struct v4l2_input input; //視頻輸入
struct v4l2_standard std;//視頻的制式,比如PAL,NTSC
struct v4l2_format fmt;//幀的格式,比如寬度,高度等
struct v4l2_buffer buf;//代表驅動中的一幀
v4l2_std_id stdid;//視頻制式,例如:V4L2_STD_PAL
struct v4l2_queryctrl query;//查詢的控制
struct v4l2_control control;//具體控制的值

  open(CAPTURE_DEVICE, O_RDWR | O_NONBLOCK, 0))關於阻塞模式和非阻塞模式,應用程序能夠使用阻塞模式或非阻塞模式打開視頻設備,如果使用非阻塞模式調用視頻設備,即使尚未捕獲到信息,驅動依舊會把緩存(DQBUFF)里的東西返回給應用程序。

 

 

 

參考:http://blog.csdn.net/luckywang1103/article/details/17406029

關於如何創建設備節點的:用戶空間的udev會根據device_create創建相應的設備節點;這里只是簡單說說我的理解class_create與class_register功能上類似,只是class_register需要分配struct class對象內存並初始化。自動創建設備節點class_create與device_create或者class_register,device_register,用戶空間的udev會根據device_create創建相應的設備節點

 linux中class_create和class_register說明:http://www.cnblogs.com/skywang12345/archive/2013/05/15/driver_class.html  (未看

v4l2驅動架構解析與開發引導: http://www.360doc.com/content/13/1010/16/7775902_320343471.shtml

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM