當前位置:首頁 » 編程軟體 » v4l2編程

v4l2編程

發布時間: 2024-01-22 16:17:02

linux下怎麼樣進行攝像頭編程

在linux下所有設備都是文件。所以對攝像頭的操作其實就是對文件的操作。USB攝像頭的設備文件就是在/dev目錄下的video0(假如只有一個攝像頭)。在linux下操作攝像頭就是使用v4l2對攝像頭進行的操作,操作步驟如下

  • 打開設備文件。

  • int fd=open(」/dev/video0″,O_RDWR);

  • 2. 取得設備的capability,看看設備具有什麼功能,比如是否具有輸入,或者音頻輸入輸出等。VIDIOC_QUERYCAP,struct v4l2_capability

  • v4l2_std_id std;

  • do {

  • ret= ioctl(fd, VIDIOC_QUERYSTD, std);

  • } while (ret == -1 errno == EAGAIN);

  • switch (std) {

  • case V4L2_STD_NTSC:

  • //……

  • case V4L2_STD_PAL:

  • //……

  • }

  • 3. 選擇輸入,一個設備可以有多個輸入。VIDIOC_S_INPUT,struct v4l2_input(可不要)

  • 4. 設置的制式和幀格式,制式包括PAL,NTSC,幀的格式個包括寬度和高度等。

  • VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format

  • struct v4l2_format fmt;

  • memset ( fmt, 0, sizeof(fmt) );

  • fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  • fmt.fmt.pix.width = 320;

  • fmt.fmt.pix.height = 240;

  • fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;

  • if (ioctl(fd, VIDIOC_S_FMT, fmt) < 0)

  • {

  • printf("set format failed ");

  • //return 0;

  • }

  • 5. 向驅動申請幀緩沖,一般不超過5個。struct v4l2_requestbuffers

  • struct v4l2_requestbuffers req;

  • memset(req, 0, sizeof (req));

  • req.count = 4;

  • req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  • req.memory = V4L2_MEMORY_MMAP;

  • if (ioctl(fd,VIDIOC_REQBUFS,req) == -1)

  • {

  • perror("VIDIOC_REQBUFS error ");

  • //return -1;

  • }

  • 6.申請物理內存

  • 將申請到的幀緩沖映射到用戶空間,這樣就可以直接操作採集到的幀了,而不必去復制。將申請到的幀緩沖全部入隊列,以便存放採集到的數據.VIDIOC_QBUF,struct v4l2_buffer

  • VideoBuffer* buffers = calloc( req.count, sizeof(VideoBuffer) );

  • printf("sizeof(VideoBuffer) is %d ",sizeof(VideoBuffer));

  • struct v4l2_buffer buf;

  • for (numBufs = 0; numBufs < req.count; numBufs++)

  • {

  • memset( buf, 0, sizeof(buf) );

  • buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  • buf.memory = V4L2_MEMORY_MMAP;

  • buf.index = numBufs;

  • if (ioctl(fd, VIDIOC_QUERYBUF, buf) < 0)

  • {

  • printf("VIDIOC_QUERYBUF error ");

  • //return -1;

  • }

  • printf("buf len is %d ",sizeof(buf));

  • //內存映射

  • buffers[numBufs].length = buf.length;

  • buffers[numBufs].offset = (size_t) buf.m.offset;

  • buffers[numBufs].start = mmap (NULL, buf.length,PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);

  • printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d ",buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);

  • printf("buf2 len is %d ",sizeof(buffers[numBufs].start));

  • if (buffers[numBufs].start == MAP_FAILED)

  • {

  • perror("buffers error ");

  • //return -1;

  • }

  • if (ioctl (fd, VIDIOC_QBUF, buf) < 0)

  • {

  • printf("VIDIOC_QBUF error ");

  • //return -1;

  • }

  • }

  • 7. 開始的採集。

  • enum v4l2_buf_type type;

  • type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  • if (ioctl (fd, VIDIOC_STREAMON, type) < 0)

  • {

  • printf("VIDIOC_STREAMON error ");

  • // return -1;

  • }

  • 8. 出隊列以取得已採集數據的幀緩沖,取得原始採集數據。VIDIOC_DQBUF, 將緩沖重新入隊列尾,這樣可以循環採集。VIDIOC_QBUF

  • if (ioctl(fd, VIDIOC_DQBUF, buf) < 0)

  • {

  • perror("VIDIOC_DQBUF failed. ");

  • //return -1;

  • }

  • buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  • buf.memory = V4L2_MEMORY_MMAP;

  • unsigned char *ptcur = buffers[numBufs].start;

  • DEBUG("buf.bytesused = %d ",buf.bytesused);

  • int i1;

  • for(i1=0; i1<buf.bytesused; i1++)

  • {

  • if((buffers[numBufs].start[i1] == 0xFF) (buffers[numBufs].start[i1+1] == 0xC4))

  • {

  • DEBUG("huffman table finded! buf.bytesused = %d FFC4 = %d ",buf.bytesused,i1);

  • break;

  • }

  • }

  • if(i1 == buf.bytesused)printf("huffman table don't exist! ");

  • int i;

  • for(i=0; i<buf.bytesused; i++)

  • {

  • if((buffers[numBufs].start[i] == 0xFF) (buffers[numBufs].start[i+1] == 0xD8)) break;

  • ptcur++;

  • }

  • DEBUG("i=%d,FF=%02x,D8=%02x ",i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);

  • int imagesize =buf.bytesused - i;

  • DEBUG("buf.bytesused = %d ",buf.bytesused);

  • DEBUG ("imagesize = %d ",imagesize);

  • 9. 停止的採集。VIDIOC_STREAMOFF

  • 10. 關閉設備。close(fd);

Ⅱ 想學習Linux 驅動,需要什麼知識

首先,接觸linux操作系統,在你的電腦上裝一個linxu操作系統(建議ubuntu,比較友好),熟悉經常要用的命令,熟悉環境(建議看「鳥哥的linux私房菜」)。

其次,閱讀經典書籍是不可少的,建議先看ldd前四章,大概了解linux驅動的框架,驅動是做什麼的,該如何寫驅動,那本書上有一些例子,可以在你的電腦上編譯,執行看看。後面的章節在結合自己的情況而定。

第三,建議閱讀ulk(understanding the linux kernel)所有的內容,了解linux內核的一些基本知識,在心中建立一個框架,不必完全懂,深入了解就好,以後經常翻翻,受益無窮!

第四,別著急,這才是你真的進入linux驅動的第一步,花點錢買個開發板吧,然後了解代碼的編譯,下載,看看板子的datasheet,針對自己感興趣的深入研究。建議學習流程,led燈控制---tp---i2c匯流排-----lcd-----camera----flash----wifi/bt等。因為這個裡面牽涉了甚多內核的子系統(input,v4l2,fb等
),所以可能要多話時間看代碼,了解代碼的框架,設計的思想等,只要一步一個腳印,一定會有所成。

第五,因為現在的移動設備大多數都是android的了,所以你就要看看linux kernel在android的作用,然後往上看看,看看hal層的代碼,這些在調試中都是需要的,如果有興趣,更加可以看看framework的代碼了,學習android一些工作機制,類似於surfaceflinger,audioflinger等等。。

熱點內容
膏子葯存儲 發布:2024-11-16 16:02:34 瀏覽:682
安卓紅包雷神怎麼樣 發布:2024-11-16 15:53:17 瀏覽:392
支付密碼是對的怎麼辦 發布:2024-11-16 15:45:20 瀏覽:176
安卓動態庫反編譯 發布:2024-11-16 15:23:04 瀏覽:374
什麼是奧維伺服器lp地址 發布:2024-11-16 15:20:13 瀏覽:10
c數字圖像處理源碼 發布:2024-11-16 15:13:28 瀏覽:402
為什麼蘋果處理器一直比安卓好 發布:2024-11-16 15:13:22 瀏覽:153
折標演算法 發布:2024-11-16 15:07:10 瀏覽:475
如何做好編譯類節目 發布:2024-11-16 14:56:51 瀏覽:977
正版激活伺服器搭建 發布:2024-11-16 14:47:04 瀏覽:778