午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

V4L2驅(qū)動(dòng)的移植與應(yīng)用(一)

 joy_chen 2014-04-17

V4L2(video for linux) 可以支持多種設(shè)備,它可以有以下5種接口:

1、視頻采集接口(video capture interface):這種應(yīng)用的設(shè)備可以是高頻頭或者攝像頭.V4L2的最初設(shè)計(jì)就是應(yīng)用于這種功能的.下面也是著重講解這種應(yīng)用;

2、視頻輸出接口(video output interface):可以驅(qū)動(dòng)計(jì)算機(jī)的外圍視頻圖像設(shè)備——像可以輸出電視信號(hào)格式的設(shè)備;

3、直接傳輸視頻接口(video overlay interface):它的主要工作是把從視頻采集設(shè)備采集過來的信號(hào)直接輸出到輸出設(shè)備之上,而不用經(jīng)過系統(tǒng)的CPU;

4、視頻間隔消隱信號(hào)接口(VBI interface):它可以使應(yīng)用可以訪問傳輸消隱期的視頻信號(hào);

5、收音機(jī)接口(radio interface):可用來處理從AMFM高頻頭設(shè)備接收來的音頻流;

V4L2驅(qū)動(dòng)的主要功能是使程序有發(fā)現(xiàn)設(shè)備的能力和操作設(shè)備.它主要是用過一系列的回調(diào)函數(shù)來實(shí)現(xiàn)這些功能.像設(shè)置高頻頭的頻率,幀頻,視頻壓縮格式和圖像像參數(shù)等等.

一、V4L2移植

V4L2提供了三種不同的API來傳輸外圍設(shè)備和用戶空間的數(shù)據(jù)。下面就vivi(drivers/media/video/vivi.c)來講解一個(gè)V4L2驅(qū)動(dòng)的編寫。注意它是一個(gè)虛擬的設(shè)備驅(qū)動(dòng),沒有與實(shí)際的硬件打交道。
    1
、分析幾個(gè)重要數(shù)據(jù)結(jié)構(gòu):
     
vivi.c包含頭文件v4l2-device.hv4l2-ioctl.h,其中v4l2-device.h中包含了v4l2-subdev.h,v4l2-subdev.h中又包含了v4l2-common.h,v4l2-common.h中包含了v4l2-dev.h。

       v4l2-dev.h中定義了結(jié)構(gòu)體video_devicev4l2_file_operations;

v4l2-ioctl.h中定義了結(jié)構(gòu)體v4l2_ioctl_ops

v4l2-device.h中定義了結(jié)構(gòu)體v4l2_device;

1) vivi_fops

static const struct v4l2_file_operations vivi_fops = {

       .owner           = THIS_MODULE,

       .open           = vivi_open,

       .release        = vivi_close,

       .read           = vivi_read,

       .poll        = vivi_poll,

       .ioctl          = video_ioctl2, /* V4L2 ioctl handler */

       .mmap           = vivi_mmap,

};

2) vivi_ioctl_ops

static const struct v4l2_ioctl_ops vivi_ioctl_ops = {

       .vidioc_querycap      = vidioc_querycap,

       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,

       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,

       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,

       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,

       .vidioc_reqbufs       = vidioc_reqbufs,

       .vidioc_querybuf      = vidioc_querybuf,

       .vidioc_qbuf          = vidioc_qbuf,

       .vidioc_dqbuf         = vidioc_dqbuf,

       .vidioc_s_std         = vidioc_s_std,

       .vidioc_enum_input    = vidioc_enum_input,

       .vidioc_g_input       = vidioc_g_input,

       .vidioc_s_input       = vidioc_s_input,

       .vidioc_queryctrl     = vidioc_queryctrl,

       .vidioc_g_ctrl        = vidioc_g_ctrl,

       .vidioc_s_ctrl        = vidioc_s_ctrl,

       .vidioc_streamon      = vidioc_streamon,

       .vidioc_streamoff     = vidioc_streamoff,

#ifdef CONFIG_VIDEO_V4L1_COMPAT

       .vidiocgmbuf          = vidiocgmbuf,

#endif

};

       3) vivi_template

static struct video_device vivi_template = {

       .name             = "vivi",

       .fops           = &vivi_fops,

       .ioctl_ops       = &vivi_ioctl_ops,

       .minor            = -1,

       .release    = video_device_release,

 

       .tvnorms              = V4L2_STD_525_60,

       .current_norm         = V4L2_STD_NTSC_M,

};

其中函數(shù)vivi_xxxvidioc_xxx都是在vivi.c中實(shí)現(xiàn)的。如果要基于某個(gè)硬件來實(shí)現(xiàn)V4L2的接口,那這些函數(shù)就需要調(diào)用硬件的驅(qū)動(dòng)去實(shí)現(xiàn)。

4) vivi_dev
struct vivi_dev {
    struct list_head           vivi_devlist; //
內(nèi)核雙向鏈表,在內(nèi)核數(shù)據(jù)結(jié)構(gòu)里有描述

    struct semaphore           lock;   //
信號(hào)量,防止競(jìng)態(tài)訪問
    int                        users;  //
用戶數(shù)量計(jì)數(shù)
    /* various device info */
    unsigned int               resources;
    struct video_device        video_dev; //
這個(gè)成員是這個(gè)結(jié)構(gòu)的核心,用面向?qū)ο蟮脑拋碚f就是基類
    struct vivi_dmaqueue       vidq;       //DMA
隊(duì)列
    /* Several counters */
    int                        h,m,s,us,jiffies;   //
定時(shí)器定義
    char                       timestr[13];     //
其它一些資源變量.
};

    
像這樣變義的結(jié)構(gòu)在Linux C 中很普遍,這也是利用C來實(shí)現(xiàn)面向?qū)ο缶幊痰膹?qiáng)大方法。建立這個(gè)結(jié)構(gòu)對(duì)象之后,所有的操作都是基于這個(gè)結(jié)構(gòu),或者這個(gè)結(jié)構(gòu)派生出的來的其它結(jié)構(gòu)。
    5) vivi_fh
struct vivi_fh {
    struct vivi_dev            *dev;

    /* video capture */
    struct vivi_fmt            *fmt;
    unsigned int               width,height;
    struct videobuf_queue      vb_vidq;

    enum v4l2_buf_type         type;
};

    
這個(gè)結(jié)構(gòu)即是vivi_dev結(jié)構(gòu)的更深層次封裝,基于那個(gè)結(jié)構(gòu)加入了更多的描述信息,如視頻制式、視頻畫面大小、視頻緩沖隊(duì)列等等。在open的時(shí)候,會(huì)把這個(gè)結(jié)構(gòu)賦給file結(jié)構(gòu)中的private_data域。在釋放設(shè)備時(shí)注銷.其它的像ioctl,mmapread,write等等都會(huì)用到這個(gè)結(jié)構(gòu),其實(shí)整個(gè)模塊的編寫的cdev差不多。只是視頻設(shè)備的基類是video_device,而字符設(shè)備的基類是cdev而已。

    2、數(shù)據(jù)傳輸方式:
    
在設(shè)備與應(yīng)用程序之間有三種數(shù)據(jù)傳輸方式:

    1
readwrite這種方式,它像其它設(shè)備驅(qū)動(dòng)一樣,但是這種方式很慢,對(duì)于數(shù)據(jù)視頻流不能滿足其要求;

2)直接的內(nèi)存訪問,可以通過其映射方式來傳輸(IO數(shù)據(jù)流,交換指向緩沖區(qū)指針的方法);這是視頻設(shè)備通常用的方法,采用mmap()的方法,即有內(nèi)核空間里開辟內(nèi)存,再在程序里把這部分的內(nèi)存映射到程序空間。如果有設(shè)備內(nèi)存,即直接映射到設(shè)備的內(nèi)核,這種性能更高。
    3
)異步IO口訪問,但是這種方法在V4L2模塊中還沒有實(shí)現(xiàn)。(重要:需要確認(rèn)

     
vivi中的mmap是利用第二種方法來實(shí)現(xiàn)的,這也是視頻設(shè)備常用的方法:
static int
vivi_mmap(struct file *file, struct vm_area_struct * vma)
{
    struct vivi_fh *fh = file->private_data;
    int ret;

    dprintk (1,"mmap called, vma=0x%08lx/n",(unsigned long)vma);

    ret=videobuf_mmap_mapper(&fh->vb_vidq, vma);

    dprintk (1,"vma start=0x%08lx, size=%ld, ret=%d/n",
        (unsigned long)vma->vm_start,
        (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
        ret);

    return ret;
}
    
videobuf_mmap_mapper(&fh->vb_vidq, vma);  
這個(gè)核心函數(shù)把設(shè)備的I/O內(nèi)存或者設(shè)備內(nèi)存映射到系統(tǒng)為它開辟的虛擬內(nèi)存。


    3
、操控設(shè)備的實(shí)現(xiàn): ioctl
static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl);  
}

    vivi_do_ioctl 
這個(gè)函數(shù)里調(diào)用一些命令來設(shè)備V4L2模塊中的一些結(jié)構(gòu)參數(shù)來改變或者獲取設(shè)備的參數(shù)。(待續(xù))

http://blog.csdn.net/wxzking/article/details/6225170

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多