亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

v4l2簡介

系統 2095 0

V4L是linux內核中關于視頻設備的子系統,為linux下的視頻驅動提供了統一的接口,使應用程序可以使用統一的API操作不同的視頻設備,簡化視頻系統的開發與維護

V4L2相比與V4L有更好的擴展性和靈活性

(一)V4L2支持設備:

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

1)視頻采集接口

2)視頻輸出接口

3)直接傳輸視頻接口:將視頻采集設備上采集的信號直接輸出到視頻輸出設備上,不用經過系統CPU

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

5)收音機接口:

?

(二)V4L2設備處理流程

打開V4L2設備節點

      
        int
      
       fd = open(
      
        "
      
      
        /dev/video0
      
      
        "
      
      ,O_RDWR |O_NONBLOCK);
    

配置設備/查詢設備屬性

      
        int
      
       ioctl (
      
        int
      
       fd, unsigned 
      
        long
      
      
        int
      
       request, ...
      
        /*
      
      
        args
      
      
        */
      
      ) ;
    

常見的request命令:

VIDIOC_REQBUFS:在內核空間中分配幀緩沖區

      
        struct
      
      
         v4l2_requestbuffers req;

req.count
      
      =
      
        4
      
      
        ;

req.type
      
      =
      
        V4L2_BUF_TYPE_VIDEO_CAPTURE;

req.memory
      
      =
      
        V4L2_MEMORY_MMAP;

ioctl(fd,VIDIOC_REQBUFS,
      
      &req);
    

VIDIOC_QUERYBUF:將REQBUFS中分配的緩存轉換成物理地址,并將物理地址映射到用戶空間

      
        for
      
       (n_buffers = 
      
        0
      
      ; n_buffers < req.count; ++
      
        n_buffers)

{

        
      
      
        struct
      
      
         v4l2_buffer buf;

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

        buf.type 
      
      =
      
        V4L2_BUF_TYPE_VIDEO_CAPTURE;

        buf.memory 
      
      =
      
        V4L2_MEMORY_MMAP;

        buf.index 
      
      =
      
        n_buffers;

        
      
      
        if
      
       (-
      
        1
      
       == ioctl(fd, VIDIOC_QUERYBUF, &
      
        buf))

        {

                printf(
      
      
        "
      
      
        error in VIDIOC_QUERYBUF\n
      
      
        "
      
      
        );

                
      
      
        return
      
       -
      
        1
      
      
        ;

        }

        buffers[n_buffers].length
      
      =
      
         buf.length;

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

        
      
      
        if
      
       (MAP_FAILED==
      
         buffers[n_buffers].start)

                
      
      
        return
      
       -
      
        1
      
      
        ;

}
      
    

VIDIOC_QUERYCAP:查詢驅動功能

      
        struct
      
      
         v4l2_capability cap;


      
      
        if
      
      ( ioctl(fd,VIDIOC_QUERYCAP,&cap) == -
      
        1
      
      
        )

        printf(
      
      
        "
      
      
        error\n
      
      
        "
      
      
        );

printf(
      
      
        "
      
      
        capability:\n
      
      
        "
      
      
        );

printf(
      
      
        "
      
      
        driver:%s\n
      
      
        "
      
      
        ,cap.driver);

printf(
      
      
        "
      
      
        card:%s\n
      
      
        "
      
      
        ,cap.card);

printf(
      
      
        "
      
      
        bus info:%s\n
      
      
        "
      
      
        ,cap.bus_info);

printf(
      
      
        "
      
      
        version:%d\n
      
      
        "
      
      
        ,cap.version);

printf(
      
      
        "
      
      
        capabilities:%x\n
      
      
        "
      
      ,cap.capabilities);
    

VIDIOC_ENUM_FMT:獲取當前驅動支持的視頻格式

      
        struct
      
      
         v4l2_fmtdesc fmtdesc;

fmtdesc.index 
      
      = 
      
        0
      
      
        ;

fmtdesc.type
      
      =
      
        V4L2_BUF_TYPE_VIDEO_CAPTURE;

printf(
      
      
        "
      
      
        fmtdesc:\n
      
      
        "
      
      
        );


      
      
        while
      
      (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -
      
        1
      
      
        )

{

        printf(
      
      
        "
      
      
        \t%d.%s\n
      
      
        "
      
      ,fmtdesc.index+
      
        1
      
      
        ,fmtdesc.description);

        fmtdesc.index
      
      ++
      
        ;

}
      
    

VIDIOC_G/S_FMT:讀取/設置當前驅動的視頻捕捉格式

      
        struct
      
      
         v4l2_format format;

memset(
      
      &format, 
      
        0
      
      , 
      
        sizeof
      
      (
      
        struct
      
      
         v4l2_format));

format.type 
      
      =
      
         V4L2_BUF_TYPE_VIDEO_CAPTURE;


      
      
        if
      
      ( ioctl(fd, VIDIOC_G_FMT, &format) == -
      
        1
      
      
        )

{

        printf(
      
      
        "
      
      
        VIDIOC_G_FMT error\n
      
      
        "
      
      
        );

        
      
      
        return
      
       -
      
        1
      
      
        ;

}


      
      
        struct
      
      
         v4l2_pix_format pix_format;

pix_format 
      
      =
      
         format.fmt.pix;

printf(
      
      
        "
      
      
        pix_format\n
      
      
        "
      
      
        );

printf(
      
      
        "
      
      
        width:%d\n
      
      
        "
      
      
        ,pix_format.width);

printf(
      
      
        "
      
      
        height:%d\n
      
      
        "
      
      
        ,pix_format.height);

printf(
      
      
        "
      
      
        bytesperline:%d\n
      
      
        "
      
      
        ,pix_format.bytesperline);

printf(
      
      
        "
      
      
        sizeimage:%d\n
      
      
        "
      
      ,pix_format.sizeimage);
    

VIDIOC_TRY_FMT:驗證當前驅動的顯示格式

VIDIOC_CROPCAP:查詢驅動的修剪能力

VIDIOC_G/S_CROP:讀取/設置視頻信號的邊框

      
        struct
      
      
         v4l2_cropcap cropcap;


      
      
        struct
      
      
         v4l2_crop crop;

cropcap.type 
      
      =
      
         V4L2_BUF_TYPE_VIDEO_CAPTURE;  


      
      
        if
      
      (
      
        0
      
       == ioctl(fd, VIDIOC_CROPCAP, &
      
        cropcap))  

{  

        crop.type 
      
      =
      
         V4L2_BUF_TYPE_VIDEO_CAPTURE;  

        crop.c 
      
      =
      
         cropcap.defrect;  

        
      
      
        if
      
      (-
      
        1
      
       == ioctl(fd, VIDIOC_S_CROP, &
      
        crop))

        {

                printf(
      
      
        "
      
      
        VIDIOC_S_CROP error\n
      
      
        "
      
      
        );

                
      
      
        return
      
       -
      
        1
      
      
        ;

        }

}
      
    

VIDIOC_QBUF:把緩存區放入緩存隊列

VIDIOC_DQBUF:把緩存去從緩存隊列中取出

      unsigned 
      
        int
      
      
         i;


      
      
        enum
      
      
         v4l2_buf_type type;


      
      
        for
      
       (i = 
      
        0
      
      ; i< 
      
        4
      
      ; ++
      
        i)

{

        
      
      
        struct
      
      
         v4l2_buffer buf;

        buf.type 
      
      =
      
        V4L2_BUF_TYPE_VIDEO_CAPTURE;

        buf.memory 
      
      =
      
        V4L2_MEMORY_MMAP;

        buf.index 
      
      =
      
         i;

        ioctl (fd,VIDIOC_QBUF, 
      
      &
      
        buf);

}

type 
      
      =
      
        V4L2_BUF_TYPE_VIDEO_CAPTURE;

ioctl (fd,VIDIOC_STREAMON, 
      
      &
      
        type);


      
      
        struct
      
      
         v4l2_buffer buf;

buf.type 
      
      =
      
         V4L2_BUF_TYPE_VIDEO_CAPTURE;

buf.memory 
      
      =
      
        V4L2_MEMORY_MMAP;


      
      
        if
      
      ( ioctl (fd,VIDIOC_DQBUF, &buf)==-
      
        1
      
      
        )

{

        printf(
      
      
        "
      
      
        error in VIDIOC_DQBUF\n
      
      
        "
      
      
        );

        
      
      
        return
      
       -
      
        1
      
      
        ;

}
      
    

VIDIOC_STREAMON:開始視頻顯示函數

VIDIOC_STREAMOFF:結束視頻顯示函數

VIDIOC_QUERYSTD:檢查當前視頻設備支持的標準,亞洲一般使用PAL制式攝像頭,歐洲一般使用NTSC攝像頭

      
        v4l2_std_id std;


      
      
        int
      
      
         ret;


      
      
        do
      
      
        

{

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

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


      
      
        switch
      
      
        (std)

{


      
      
        case
      
      
         V4L2_STD_NTSC:

   
      
      
        //


      
      
        case
      
      
         V4L2_STD_PAL:

   
      
      
        //
      
         

} 
    

處理v4l2視頻數據

v4l2設定了三種應用程序與驅動的交互方式:

1)直接讀取設備文件方式read/write

2)mmap映射方式

3)用戶指針方式

mmap方式:驅動將內部數據空間映射到應用程序空間上,雙方直接在這個空間上進行數據交換

用戶指針方式:首先由應用程序申請一段緩沖區,然后將緩沖區傳給驅動,驅動將其作為緩沖區,從而實現內存共享

直接read/write:一般配合select使用,直接讀取設備文件的方式進行I/O

關閉設備

調用close關閉文件描述符,如果進行了內存映射,關閉之前還需要munmap解除映射

v4l2簡介


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美日韩亚 | 91视频一区二区 | 国产精品免费看 | 久久精品中文字幕极品 | 国产在线视频色综合 | 13一14周岁毛片免费 | 亚洲精品视频一区 | 青春草国产成人精品久久 | 农村妇女又色黄一级毛片 | 国语精品视频在线观看不卡 | 热久久精品 | 欧美ⅹxxxx视频| 夜夜爽日日澡人人添 | 国产成在线观看免费视频成本人 | 亚洲国产一区在线二区三区 | 日韩欧美色视频 | 毛片一区| 亚洲欧美日韩在线 | 青青热久久久久综合精品 | 欧美人交性视频在线香蕉 | 日日天日日夜日日摸 | 久久视频这里只有精品 | 九九在线免费视频 | 久久国产高清字幕中文 | 国产99对白在线播放 | 免费看曰批女人爽的视频网址 | www.啪啪.com | 国产精品高清视亚洲乱码 | 国产亚洲男人的天堂在线观看 | 九九热在线免费观看 | 性欧美高清久久久久久久 | 亚洲一区不卡视频 | 88国产经典欧美一区二区三区 | 久久黄色视屏 | 亚洲香蕉毛片久久网站老妇人 | 色婷婷狠狠久久综合五月 | 国产深夜| 日本3p视频在线看高清 | 97精品免费视频 | 欧美激情亚洲激情 | 99视频久久 |