linux摄像头驱动.docx

上传人:b****3 文档编号:5920072 上传时间:2023-05-09 格式:DOCX 页数:55 大小:274.72KB
下载 相关 举报
linux摄像头驱动.docx_第1页
第1页 / 共55页
linux摄像头驱动.docx_第2页
第2页 / 共55页
linux摄像头驱动.docx_第3页
第3页 / 共55页
linux摄像头驱动.docx_第4页
第4页 / 共55页
linux摄像头驱动.docx_第5页
第5页 / 共55页
linux摄像头驱动.docx_第6页
第6页 / 共55页
linux摄像头驱动.docx_第7页
第7页 / 共55页
linux摄像头驱动.docx_第8页
第8页 / 共55页
linux摄像头驱动.docx_第9页
第9页 / 共55页
linux摄像头驱动.docx_第10页
第10页 / 共55页
linux摄像头驱动.docx_第11页
第11页 / 共55页
linux摄像头驱动.docx_第12页
第12页 / 共55页
linux摄像头驱动.docx_第13页
第13页 / 共55页
linux摄像头驱动.docx_第14页
第14页 / 共55页
linux摄像头驱动.docx_第15页
第15页 / 共55页
linux摄像头驱动.docx_第16页
第16页 / 共55页
linux摄像头驱动.docx_第17页
第17页 / 共55页
linux摄像头驱动.docx_第18页
第18页 / 共55页
linux摄像头驱动.docx_第19页
第19页 / 共55页
linux摄像头驱动.docx_第20页
第20页 / 共55页
亲,该文档总共55页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

linux摄像头驱动.docx

《linux摄像头驱动.docx》由会员分享,可在线阅读,更多相关《linux摄像头驱动.docx(55页珍藏版)》请在冰点文库上搜索。

linux摄像头驱动.docx

linux摄像头驱动

基于V4L2的视频驱动开发

编写基于V4L2视频驱动主要涉及到以下几个知识点:

●摄像头方面的知识

  要了解选用的摄像头的特性,包括访问控制方法、各种参数的配置方法、信号输出类型等。

●Camera解码器、控制器

  如果摄像头是模拟量输出的,要熟悉解码器的配置。

最后数字视频信号进入camera控制器后,还要熟悉camera控制器的操作。

●V4L2的API和数据结构

  编写驱动前要熟悉应用程序访问V4L2的方法及设计到的数据结构。

●V4L2的驱动架构

  最后编写出符合V4L2规范的视频驱动。

本文介绍基于S3C2440硬件平台的V4L2视频驱动开发。

摄像头采用OmniVision公司的OV9650和OV9655。

主要包含以下几个方面的内容:

视频驱动的整体驱动框架

●    3C2440camera控制器+ov9650(ov9655)

        ●    V4L2API及数据结构

        ●    V4L2驱动框架

        ●    ov9650(ov9655)+s3c2440+V4L2实例

一、视频驱动的整体框架

视频驱动的整体框架见下图:

二、S3C2440camera控制器+ov9650(ov9655)

(1)S3C2440camera控制器介绍

S3C2440支持ITU-RBT601/656格式的数字图像输入,支持的2个通道的DMA,Preview通道和Codec通道,参见下图。

Preview通道可以将YCbCr4:

2:

2格式的图像转换为RGB(16bit或24bit)格式的数据,并存放于为PreviewDMA分配的内存中,最大分辨率为640*480。

主要用于本地液晶屏显示。

如果将PreviewDMA的内存和Framebuffer内存重叠的话,就可以实现采集直接输出到液晶屏上了。

Codec通道可以输出YCbCr4:

2:

0或YCbCr4:

2:

2格式到为CodecDMA分配的内存中。

最大分辨率为4096*4096。

主要用于图像的编解码处理。

上图中的windowcut功能是指在图像可以先做一个裁剪。

通过设置CIWDOFST完成此功能,见下图。

图像进入P、C通道后,各自的scaler单元还可以对其进行缩放、旋转等处理。

S3C2440camera控制器支持乒乓存储。

为了防止采集和输出之间的冲突,采用了乒乓存储方式。

每次采集一帧后,自动转到下一个存储区。

如果你因为内存空间不足,不想使用此功能的话,可以将四个区域设置到同一块空间。

在做图像处理时,需要关注到最后存储区中的图像格式,如codec通道硬件自动把Y、Cb、Cr分离存储。

S3C2440camera控制器LastIRQ功能的使用,也是需要掌握的。

如果处理不好,输出的图像效果会受影响。

控制器会在每个VSYNC下降沿判断ImgCptEn信号等命令。

如果在下降沿发现ImgCptEn信号有效,则产生IRQ中断。

然后才开始一帧图像的真正采集。

而如果在VSYNC下降沿判断到ImgCptEn为低电平且之前LastIRQEn没有使能,则不会产生任何中断,且不会再进行下一帧的采集。

如果你想在ImgCptEn关闭后,一帧采集完后产生一个中断通知你,那么就需要在最后一次中断产生前(stopcapturing后的vysnc下将沿)使能lastirq就可以了。

我在移植linux驱动时就遇到了一个LastIRQ的问题。

现象是输出图像上面总是有一条比其它部分反应慢。

采集运动图像,就能看出现象。

查看代码是因为没有设立lastirq,因为每次如果不在lastirq产生的情况下读取,图像缓冲中的数据是不稳定的,可能照成图像不完整。

修改代码支持lastirq后,问题解决。

Camera控制器时钟设置也是需要注意的,ov9650需要Camera控制器为其提供时钟。

提供给外部摄像头的时钟是由UPLL输出时钟分频得到的。

而CAMIF的时钟是由HCLK提供的。

本例中,提供给ov9650的时钟为24M。

(2)ov9650(ov9655)设置方法

OV9650是OmniVision公司的COMS摄像头,130万像素,支持SXVGA、VGA、QVGA、CIF等图像输出格式。

最大速率在SXVGA时为15fps,在VGA时为30fps。

OV9650摄像头时序如下图:

上图中D[9:

2]用于8-bitYUV或者RGB565/RGB555(D[9]MSB、D[2]LSB)。

D[9:

0]用于10-bitRGB。

本例中使用8-bitYUV模式。

我手边开发板的Camera和S3C2440的接线原理图如下(对应camera中具体的信号名称参见前文的驱动整体架构图)。

注:

GPG12用于PWEN信号

OV9650摄像头设置方法是通过SCCB总线设置

SCCB可以看作是一种简化的I2C总线,可以使用IO模拟SCCB时序。

(3)编写ARM测试代码测试camera功能

在Keil环境下编写一个测试代码完成从摄像头采集图像输出到液晶屏。

下面列出程序的流程。

(4)编写测试代码过程中常见的问题

●    摄像头寄存器的配置

因为摄像头有很多寄存器,可能一下无法理解里面所有的配置含义,所以开始时希望得到一份可用的配置。

但往往从别人的测试代码中拿到配置后,仍然无法使用。

我这里列出几个可能的原因:

(1)摄像头中的图像输出格式和你在camera控制器中设置的不一致,同一个摄像头可以设置多种输入格式,如:

YCbYCr或CbYCrY。

(2)图像输出的一些时序和你的camera控制器设置不一致,摄像头可以设置一些时序,如:

图像数据在CAMPCLK的上升沿有效还是下降沿有效。

(3)注意输出图像的格式和Framebuffer控制器的匹配,如字节顺序等问题。

●    Ov9650和ov9655的使用区别

这里主要列出两者之间在复位信号上有差别,ov9650是高电平复位,而ov9655是低电平复位。

三、V4L2API及数据结构

V4L2是V4L的升级版本,为linux下视频设备程序提供了一套接口规范。

包括一套数据结构和底层V4L2驱动接口。

1、常用的结构体在内核目录include/linux/中定义

structv4l2_requestbuffersength=;tart=mmap(NULL,,

PROT_READ|PROT_WRITE,

MAP_SHARED,

fd,

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

return-1;

}

(8)开始采集视频

intbuf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

intret=ioctl(fd,VIDIOC_STREAMON,&buf_type);

(9)取出FIFO缓存中已经采样的帧缓存

structv4l2_bufferbuf;

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

=V4L2_BUF_TYPE_VIDEO_CAPTURE;

=V4L2_MEMORY_MMAP;

=0;ame="s3c2440camif",

.type=VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_SUBCAPTURE,

.fops=&camif_fops,

.minor=-1,

.release=camif_dev_release,

.vidioc_querycap=vidioc_querycap,

.vidioc_enum_fmt_cap=vidioc_enum_fmt_cap,

.vidioc_g_fmt_cap=vidioc_g_fmt_cap,

.vidioc_s_fmt_cap=vidioc_s_fmt_cap,

.vidioc_queryctrl=vidioc_queryctrl,

.vidioc_g_ctrl=vidioc_g_ctrl,

.vidioc_s_ctrl=vidioc_s_ctrl,

};

staticstructfile_operationscamif_fops=

{

.owner=THIS_MODULE,

.open=camif_open,

.release=camif_release,

.read=camif_read,

.poll=camif_poll,

.ioctl=video_ioctl2,/*V4L2ioctlhandler*/

.mmap=camif_mmap,

.llseek=no_llseek,

};

注意:

video_ioctl2是中是实现的。

video_ioctl2中会根据ioctl不同的cmd来

调用video_device中的操作方法。

3、Video核心层的实现参见内核/drivers/media/

(1)注册256个视频设备

staticint__initvideodev_init(void)

{

intret;

if(register_chrdev(VIDEO_MAJOR,VIDEO_NAME,&video_fops)){

return-EIO;

}

ret=class_register(&video_class);

……

}

上面的代码注册了256个视频设备,并注册了video_class类。

video_fops为这256个设备共同的操作方法。

(2)V4L2驱动注册函数的实现

intvideo_register_device(structvideo_device*vfd,inttype,intnr)

{

inti=0;

intbase;

intend;

intret;

char*name_base;

switch(type)wner=THIS_MODULE,

.llseek=no_llseek,

.open=video_open,

};

奇怪吧,这里只实现了open操作。

那么后面的其它操作呢?

还是先看看video_open吧。

staticintvideo_open(structinode*inode,structfile*file)

{

unsignedintminor=iminor(inode);

interr=0;

structvideo_device*vfl;

conststructfile_operations*old_fops;

if(minor>=VIDEO_NUM_DEVICES)

return-ENODEV;

mutex_lock(&videodev_lock);

vfl=video_device[minor];

if(vfl==NULL){

mutex_unlock(&videodev_lock);

request_module("char-major-%d-%d",VIDEO_MAJOR,minor);

mutex_lock(&videodev_lock);

vfl=video_device[minor];Buffer,则二者的关联关系为:

如果P通道格式为RGB24,图像宽度为PrDstWidth,图像高度为PrDstHeight,分配的DMA地址为PrFrame.Buffer,则二者的关联关系为:

2.3配置CAMIF相关寄存器

①把输入视频信号宽度配置为720像素,高度配置为288像素;

②把输入视频信号格式配置为BT.656YCbcr4:

2:

2格式;

③把输入视频信号顺序配置为CbYCr;

④根据用户的LCD显示终端的分辨率配置P通道的图像宽度、高度像素和格式;

⑤根据用户对图像的处理需求来配置C通道的图像宽度、高度像素和格式;

⑥配置C通道的缩放系数;

⑦配置P通道的缩放系数;

⑧把C通道的DMA地址配置给4组起始地址寄存器;

⑨把P通道的DMA地址配置给4组起始地址寄存器。

2.4创建camera流式驱动接口函数

WinCE下的硬件驱动程序大多采用流式驱动来开发,因为它有一个一致的接口函数供用户调用。

此处,把接口函数命名为:

CAM_Close()、CAM_Deinit()、CAM_Init()、CAMIOControl()、CAM()pen()、CAMPowerDown()、CAM_PowerUp()、CAM_Read()、CAM_Seek()和CAM-_Write()。

(1)CAM_Init()函数

该函数在驱动程序每次被设备管理器加载时调用。

其实现的功能如下:

配置SAA7113,分配C通道、P通道的DMA内存空间,根据输入信号源属性和输出图像、预览图像属性配置CAMIF寄存器。

创建一个事件CameraEvent,使用WinCE内核函数InterruptInitialize(SYSINIR_CAM,CameraEvent,NULL,O)把该事件与camera的逻辑中断号SYSINIR_CAM关联起来,即当中断发生时激活该事件。

创建一个中断服务线程。

在该线程内用WaitForSintgleObjcet(CameraEvent,INFINITE)函数阻塞线程,并等待CameraEvent激活。

把预览视频图像的功能放到CameraEyent激活之后完成,即把P通道缓冲区的内容拷贝到显示终端。

最后,用InterruptDone(SYSINIR_CAM)函数结束本次中断处理。

(2)CAM_IOControl()函数

可以说,该函数才真正是用户程序与驱动程序联系的主要通道,用户程序对camera接口的控制及数据采集均是通过该函数完成的。

其主要功能有:

①打开/关闭P通道或C通道输出。

②修改配置参数。

③控制输出图像的放大或缩小。

④如果需要RGB数据,则读取P通道缓冲区内容;

如果需要YCbCr数据,则读取C通道缓冲区内容。

注意,读取之前要根据状态寄存器CICOSTATUS或CIPRSTATUS的当前状态,确定访问哪一组缓冲区。

(3)CAM_Deinit()函数

当卸载本驱动时,该函数负责释放分配的内存空间和资源。

(4)CAM_Open()函数

该函数内部并没有具体的功能代码,只是当用户程序使用CreateFile(TEXT(“CAMl:

”),GENERIC_READ|GENERICWRITE,O,NULL,OP-EN_EXISTING,O,O)函数打开camera驱动时调用该函数,并返回一个文件句柄。

基于该句柄用户才能进行后续操作。

(5)CAM_Close()函数

该函数内部并没有具体的功能代码,只有当用户程序使用CloseFile(hfile)函数关闭camera驱动时才调用该函数,并释放之前返回的文件句柄。

其他接口函数没用赋予其具体功能。

结语

按照上述方法开发的驱动代码,连同其他驱动已在PB5.O环境下编译通过,生成的内核文件在原硬件平台下成功运行,P通道视频图像流畅,C通道图像质量较高。

该方法弥补了目前国内在WinCE5.O/6.O操作系统环境下CCD摄像头无法连接到S3C2440的camera接口的缺陷,为工程技术人员设计嵌入式图像采集系统时提供了一种有效手段。

v4l2驱动编写篇一--介绍

大部分所需的信息都在这里。

作为一个驱动作者,当挖掘头文件的时候,你可能也得看看include/media/,它定义了许多你将来要打交道的结构体。

一个视频驱动很可能要有处理PCI总线,或USB总线的部分。

这里我们不会花什么时间还接触这些东西。

通常会有一个内部一I2C接口,我们在这一系列的后续文章中会接触到它。

然后还有一个V4L2的子系统接口。

这个子系统是围绕video_device这个结构体建立的,它代表的是一个V4L2设备。

讲解进入这个结构体的一切,将会是这个系列中几篇文章的主题。

这里我们先有一个概览。

video_device结构体的name字段是这一类设备的名字,它会出现在内核日志和sysfs中出现。

这个名字通常与驱动的名字相同。

所表示的设备有两个字段来描述。

第一个字段(type)似乎是从V4L1的API中遗留下来的,它可以下列四个值之一:

 笔者最近有机会写了一个摄像头的驱动,是“Onelaptopperchild”项目的中摄像头专用的。

这个驱动使用了为此目的而设计的内核API:

theVideo4Linux2API。

在写这个驱动的过程中,笔者发现了一个惊人的问题:

这个API的文档工作做得并不是很好,而用户层的文档则写的,实际上,相当不错。

为了补救现在的状况,LWN将在未来的内个月里写一系列文章,告诉大家如何写V4L2接口的驱动。

V4L2有一段历史了。

大约在1998的秋天,它的光芒第一次出现在BillDirks的眼中。

经过长足的发展,它于2002年11月,发布时,融入了内核主干之中。

然而直到今天,仍有一部分内核驱不支持新的API,这种新旧API的转换工作仍在进行。

同时,V4L2API也在发展,并在版本中进行了一些重大的改变。

支持V4L2的应用依旧相对较少。

V4L2在设计时,是要支持很多广泛的设备的,它们之中只有一部分在本质上是真正的视频设备:

•videocaptureinterface(影像捕获接口)从调谐器或是摄像头上获取视频数据。

对很多人来讲,影像捕获(videocapture)是V4L2的基本应用。

由于笔者在这方面的经验是强项,这一系列文章也趋于强调捕获API,但V4L2不止这些。

•videooutputinterface(视频输出接口)允许应用使用PC的外设,让其提供视频图像。

有可能是通过电视信号的形式。

•捕获接口还有一个变体,存在于videooverlayinterface(视频覆盖接口)之中。

它的工作是方便视频显示设备直接从捕获设备上获取数据。

视频数据直接从捕获设备传到显示设备,无需经过CPU。

•VBIinterfaces(Verticalblankingintervalinterface,垂直消隐接口)提供垂直消隐期的数据接入。

这个接口包括raw和sliced两种接口,其分别在于硬件中处理的VBI数据量。

(为什么要在消隐期间接入数据呢?

看这里) 

•radiointerface(广播接口)用于从AM或FM调谐器中获得音频数据。

 

也可能出现其它种类的设备。

V4L2API中还有一些关于编译码和效果设备的stub,他们都用来转换视频数据流。

然而这块的东西尚未完成确定,更不说应用了。

还有“teletext”和”radiodatasystem”的接口,他们目前在V4L1API中实现。

他们没有移动到V4L2的API中来,而且目前也没有这方面的计划。

视频驱动与其他驱动不同之处,在于它的配置方式多种多样。

因此大部分V4L2驱动都有一些特定的代码,好让应用可以知道给定的设备有什么功能,并配置设备,使其按期望的方式工作。

V4L2的API定义了几十个回调函数,用来配置如调谐频率、窗口和裁剪、帧速率、视频压缩、图像参数(亮度、对比度…)、视频标准、视频格式等参数。

这一系列文章的很大部分都要用来考察这些配置的过程。

然后,还有一个小任务,就是有效地在视频频率下进行I/O操作。

V4L2定义了三种方法来在用户空间和外设之间移动视频数据,其中有些会比较复杂。

视频I/O和视频缓冲层,将会分成两篇文章来写,它们是用来处量一些共性的任务的。

随后的文章每几周发一篇,共会加入到下面的列表中。

 

v4l2驱动编写篇二--注册和打开 

 这篇文章是LWN写V4L2接口的设备驱动系列文章的第二篇。

没看过介绍篇的,也许可以从那篇开始看。

这一期文章将关注VideoforLinux驱动的总体结构和设备注册过程。

开始之前,有必要提一点,那就是对于搞视频驱动的人来说,有两份资料是非常有价值的。

•TheV4L2APISpecification.(V4L2API说明)这份文档涵盖了用户空间视角下的API,但在很大程度上,V4L2驱动直接实现的就是那些API。

所以大部分结构体是相同的,而且V4L2调用的语义也表述很很明了。

打印一份出来(可以考虑去掉自由文本协议的文本内容,以保护树木[前面是作者原文,节省纸张就是保护树木嘛]),放在容易够到的地方。

•内核代码中的vivi驱动,即drivers/media/video/.这是一个虚拟驱动。

它可以用来测试,却不使用任何实际硬件。

这样,它就成一个教人如何写V4L2驱动的非常好的实例。

 

首先,每个V4L2驱动都要包含一个必须的头文件:

•VFL_TYPE_GRABBER表明是一个图像采集设备–包括摄像头、调谐器,诸如此类。

•VFL_TYPE_VBI代表的设备是从视频消隐的时间段取得信息的设备。

•VFL_TYPE_RADIO代表无线电设备。

•VFL_TYPE_VTX代表视传设备。

 

如果你的设备支持上面提到的不只一种功能,那就要为每个功能注册一个V4L2设备。

然而在V4L2中,注册的每个设备都可以用作它实际支持的各种模式(就是说,你要为一个物理设备创建不多个设备节点,但你却可以调用任意一个设备节点,来实现这个物理设备支持的任意功能)。

实质上的问题是,在V4L2中,你实际上只需一个设备,注册多个V4l2设备只是为了与V4l1兼容。

 

第二个字段是type2,它以掩码的形式对设备的功能提供了更详尽的描述。

它可以包含以下值:

/*ThesedefinesareV4L1specificandshouldnotbeusedwiththeV4L2API!

  Theywillberemovedfromthisheaderinthefuture.*/

•VID_TYPE_CAPTURE它可以捕获视频数据 

•VID_TYPE_TUNER它可以接收不同的频率 

•VID_TYPE_TELETEXT它可以抓取字幕 

•VID_TYPE_OVERLAY它可以将视频数据直接覆盖到显示设备的帧缓冲区 

•VID_TYPE_CHROMAKEY一种特殊的覆盖能力,覆盖的仅是帧缓冲区中像素值为某特定值的区域 

•VID_TYPE_CLIPPING它可以剪辑覆盖数据 

•VID_TYPE_FRAMERAM它使用帧缓冲区中的存储器 

•VID_TYPE_SCALES它可以缩放视频数据 

•VID_TYPE_MONOCHROME这个是一个纯灰度设备 

•VID_TYPE_SUBCAPTURE它可以捕获图像的子区域 

•VID_TYPE_MPEG_DECODER它支持mpeg码流解码 

•VID_TYPE_MPEG_ENCODER它支持编码mpeg码流 

•VID_TYPE_MJPEG_DECODER它支持mjpeg解码 

•VID_TYPE_MJPEG_ENCODER它支持mjpe

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2