基于Mavell Pxa920 linux
手机的数码相机功能指的是手机经过内置数码相机进行拍摄静态图片或短片拍摄,做为手机的一项新的附加功能,手机的数码相机功能获得了迅速的发展。 缓存
手机摄像头分为内置与外置,内置摄像头是指摄像头在手机内部,更方便。外置手机经过数据线或者手机下部接口与数码相机相连,来完成数码相机的一切拍摄功能。 架构
处于发展阶段的手机的数码相机的性能应该也处于初级阶段,带有光学变焦的手机目前国内销售的尚未这个功能,不过相信随着手机数码相机功能的发展,带有光学变焦的手机也会逐渐上市,但大部分都拥有数码变焦功能。 ide
目前手机的数码相机功能主要包括拍摄静态图像,连拍功能,短片拍摄,镜头可旋转,自动白平衡,内置闪光灯等等。手机的拍摄功能是与其屏幕材质、屏幕的分辨率、摄像头像素、摄像头材质有直接关系。 函数
(joint photographic expert group)静态图像压缩方式。一种有损图像的压缩方式。压缩比越大,图像质量也就越差。当图像精度要求不高存储空间有限时,能够选择这种格式。目前大部分数码相机都使用JPEG格式。 性能
指的是图像中的杂点干扰,表现为图像中有固定的彩色杂点。 ui
与人的眼睛成像是类似原理,简单说就是成像范围。 spa
要求在不一样色温环境下,照白色的物体,屏幕中的图像应也是白色的。色温表示光谱成份,光的颜色。色温低表示长波光成分多。当色温改变时,光源中三基色(红、绿、蓝)的比例会发生变化,须要调节三基色的比例来达到彩色的平衡,这就是白平衡调节的实际。 code
图象传感器的图象数据被读取后,系统将对其进行针对镜头的边缘畸变的运算修正,而后通过坏像处理后被系统送进去进行白平衡处理(在不一样的环境光照 下,人类的眼睛能够把一些“白”色的物体都当作白色,是由于人眼进行了修正。可是SENSOR没有这种功能,所以须要对SENSOR输出的信号进行必定的 修正,这就是白平衡处理技术)。 orm
好的摄像头内部电源也是保证摄像头稳定工做的一个因素。
反映对色彩的识别能力和成像的色彩表现能力,就是用多少位的二进制数字来记录三种原色。实际就是A/D转换器的量化精度,是指将信号分红多少个等级,经常使用 色彩位数(bit)表示。彩色深度越高,得到的影像色彩就越艳丽动人。非专业的SENSOR通常是24位;专业型SENSOR至少是36位。24位的 SENSOR,感光单元能记录的光亮度值最多有2^8=256级,每一种原色用一个8位的二进制数字来记录,最多记录的色彩是256×256×256约 16,77万种。
36位的SENSOR,感光单元能记录的光亮度值最多有2^12=4096级,每一种原色用一个12位的二进制数字来记录,最多记录的色彩是4096×4096×4096约68.7亿种。
串行接口(RS232/422):传输速率慢,为115kbit/s。
并行接口(PP):速率能够达到1Mbit/s。
红外接口(IrDA):速率也是115kbit/s,通常笔记本电脑有此接口。
通用串行总线USB:即插即用的接口标准,支持热插拔。USB1.1速率可12Mbit/s,USB2.0可达480bit/s。
IEEE1394(火线)接口(亦称ilink):其传输速率可达100M~400Mbit/s。
RGB24,I420是目前最经常使用的两种图像格式。
RGB24:表示R、G、B三种颜色各8bit,最多可表现色。
I420:YUV格式之一。
其它格式有: RGB565,RGB444,YUV4:2:2等。
所谓分辨率就是指画面的解析度,由多少象素构成的数值越大,图像也就越清晰。分辨率不只与显示尺寸有关,还会受到显像管点距、视频带宽等因素的影 响。咱们一般所看到的分辨率都以乘法形式表现的,好比1024*768,其中的1024表示屏幕上水平方向显示的点数,768表示垂直方向的点数。
QXGA (2048 X 1536)又称300万像素
UXGA (1600X 1200)又称200万像素
SXGA(1280 x1024)又称130万像素
XGA(1024 x768)又称80万像素
SVGA(800 x600)又称50万像素
VGA(640x480)又称30万像素(35万是指648X488)
CIF(352x288) 又称10万像素
SIF/QVGA(320x240)
QCIF(176x144)
QSIF/QQVGA(160x120)
MIPI=Mobile Industry Processor Interface, 是相似SMIA的一个LVDS的一种接口,主要用在手机Camera Module上居多。
就CameraModule而言,如今Micorn和OV均推出支持MIPI接口的Sensor如Micorn的MT9D112,MT9T111和 OV的OV2650等,对于低像素的Sensor彷佛MIPI的优点不是很明显哦,可是在3MP以上就可能有些优点了。
其中以ov5640为例,其余carmera相关carmere driver 同理。
ov5640_mipi_probe() { … ccic_set_clock_mipi(); //ccic mipi clock 设置 pdata->power_on(1, 1); //power on camera i2c_set_clientdata(client, info); //初始化I2c资源 ov5640_mipi_detect(client); //camera检测 ccic_sensor_attach(client); //ccic host端与sensor driver绑定 … }
说明:camera 驱动启动时调用的初始化操做函数,包括camera上电、ccic控制器mpi clock设置、i2c端口初始化、camera检测与绑定等。
ov5640_mipi_comman() { v4l2_chip_ident_i2c_client () ov5640_mipi_reset() ov5640_mipi_enum_fmsize () ov5640_mipi_querycap () ov5640_mipi_enum_fmt () ov5640_mipi_try_fmt () ov5640_mipi_s_fmt() ov5640_mipi_queryctrl() ov5640_mipi_s_ctrl() ov5640_mipi_g_ctrl() ov5640_mipi_s_input() ov5640_mipi_streamon() ov5640_mipi_streamoff() ov5640_mipi_g_register() ov5640_mipi_s_register() }
说明:camera iocontorl函数
v4l2_chip_ident_i2c_client() //为摄像头分配一个独立字段,因为双摄像头区分之用
ov5640_mipi_reset //camera重启功能
ov5640_mipi_enum_fmsize // 枚举camera支持的priver and capture 的图像大小
ov5640_mipi_querycap //对应hal层识别的camera device的关键字符串赋值
ov5640_mipi_enum_fmt //枚举camera支持的图像格式
ov5640_mipi_try_fmt () //根据传入的图像格式及大小,计算图像的宽和高占用的字节数
ov5640_mipi_s_fmt() //根据传入的图像格式及大小,对camera寄存器进行相应的设置
ov5640_mipi_s_ctrl() //预留函数,对camera的一些特效设置,进行对应的寄存器设置,如今这部分功能已经在hal层实现。
ov5640_mipi_g_ctrl()//预留函数,获取camera的一些特效设置对应的寄存器设置值,如今这部分功能已经在hal层实现。
ov5640_mipi_s_input() //camera寄存器初始化
ov5640_mipi_streamon() //camera 数据流开
ov5640_mipi_streamoff() //camera 数据关
ov5640_mipi_g_register() //读取camera某一寄存器的值
ov5640_mipi_s_register() //设置 camera某一寄存器的值
Video4linux2(简称V4L2),是linux中关于视频设备的内核驱动。在Linux中,视频设备是设备文件,能够像访问普通文件同样对其进行读写,摄像头在/dev/video0下
1.打开设备文件。 int fd=open(”/dev/video0″,O_RDWR);
2.取得设备的capability,看看设备具备什么功能,好比是否具备视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability
3.设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
4.向驱动申请帧缓冲,通常不超过5个。struct v4l2_requestbuffers
5.将申请到的帧缓冲映射到用户空间,这样就能够直接操做采集到的帧了,而没必要去复制。mmap
6.将申请到的帧缓冲所有入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer
7.开始视频的采集。VIDIOC_STREAMON
8.出队列以取得已采集数据的帧缓冲,取得原始采集数据。VIDIOC_DQBUF
9.将缓冲从新入队列尾,这样能够循环采集。VIDIOC_QBUF
10.中止视频的采集。VIDIOC_STREAMOFF
11.关闭视频设备。close(fd);
1 VIDIOC_REQBUFS:分配内存
2 VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
3 VIDIOC_QUERYCAP:查询驱动功能
4 VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
5 VIDIOC_S_FMT:设置当前驱动的频捕获格式
6 VIDIOC_G_FMT:读取当前驱动的频捕获格式
7 VIDIOC_TRY_FMT:验证当前驱动的显示格式
8 VIDIOC_CROPCAP:查询驱动的修剪能力
9 VIDIOC_S_CROP:设置视频信号的边框
10 VIDIOC_G_CROP:读取视频信号的边框
11 VIDIOC_QBUF:把数据从缓存中读取出来
12 VIDIOC_DQBUF:把数据放回缓存队列
13 VIDIOC_STREAMON:开始视频显示函数
14 VIDIOC_STREAMOFF:结束视频显示函数
15 VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
这些IO调用,有些是必须的,有些是可选择的。
这里主要介绍920 host端 camera video控制器实现,主要基于v4l2架构,code文件见pxa910_camera.c。
如3.2中结构图所示,camera host端是被看成标准的v4l2架构来注册的的,也就是说是按照 struct video_device 结构体(标准的视频设置)来向系统注册设备的。
pxa910_camera_probe() { …… platform_set_drvdata(pdev, cam); init_waitqueue_head() request_irq() // ccic irq 中断注册 ccic_ctlr_init() //ccic 控制器初始化 video_register_device() …… }
platform_set_drvdata(pdev, cam) ://链接设备对象与设备驱动
init_waitqueue_head() ://申明等待事件,处理见ccic_v4l_poll函数
request_irq():ccic irq 中断注册,对应中断处理函数见 ccic_irq()函数
ccic_ctlr_init() :ccic 控制器初始化
video_register_device ://v4l2 video 设备注册
v4l2 video主要需实现ccic_v4l_fops : (struct v4l2_file_operations) 和ccic_ioctl_ops : (struct v4l2_ioctl_ops)
static const struct v4l2_file_operations ccic_v4l_fops = { .owner = THIS_MODULE, .open = ccic_v4l_open, //open files .release = ccic_v4l_release, //release files resource .poll = ccic_v4l_poll, //files poll 功能对于接口 .mmap = ccic_v4l_mmap, //files 内存映射接口 .ioctl = ccic_v4l_ioctl, //files 对应iocontorl操做接口 };
说明:v4l2 video做为文件接口对应的相关操做
struct v4l2_ioctl_ops ccic_ioctl_ops = { .vidioc_querycap = ccic_vidioc_querycap, .vidioc_enum_fmt_vid_cap= ccic_vidioc_enum_fmt_cap, .vidioc_try_fmt_vid_cap = ccic_vidioc_try_fmt_cap, .vidioc_s_fmt_vid_cap = ccic_vidioc_s_fmt_cap, .vidioc_g_fmt_vid_cap = ccic_vidioc_g_fmt_cap, .vidioc_enum_input = ccic_vidioc_enum_input, .vidioc_g_input = ccic_vidioc_g_input, .vidioc_s_input = ccic_vidioc_s_input, .vidioc_s_std = ccic_vidioc_s_std, .vidioc_reqbufs = ccic_vidioc_reqbufs, .vidioc_querybuf = ccic_vidioc_querybuf, .vidioc_qbuf = ccic_vidioc_qbuf, .vidioc_dqbuf = ccic_vidioc_dqbuf, .vidioc_streamon = ccic_vidioc_streamon, .vidioc_streamoff = ccic_vidioc_streamoff, .vidioc_queryctrl = ccic_vidioc_queryctrl, .vidioc_g_ctrl = ccic_vidioc_g_ctrl, .vidioc_s_ctrl = ccic_vidioc_s_ctrl, .vidioc_g_parm = ccic_vidioc_g_parm, .vidioc_s_parm = ccic_vidioc_s_parm, .vidioc_cropcap = ccic_vidioc_cropcap, .vidioc_g_register = ccic_vidioc_g_register, .vidioc_s_register = ccic_vidioc_s_register, }
说明:v4l2 video设备io contorl对应的处理函数。
ccic_vidioc_querycap() //查询驱动功能,获取camera属性
ccic_vidioc_enum_fmt_cap() 获取当前驱动支持的视频格式
ccic_vidioc_try_fmt_cap() //对应调用ov5640_mipi_try_fmt ()的接口,功能见上一章
ccic_vidioc_s_fmt_cap() //设置当前驱动的频捕获格式
ccic_vidioc_g_fmt_cap() //读取当前驱动的频捕获格式
ccic_vidioc_enum_input() //支持的camera检测,容错处理
ccic_vidioc_g_input() //获取camera id(30万sensor_selected 为0 ,500万sensor_selected为1)
ccic_vidioc_s_input() //设置要切换的camera id
ccic_vidioc_reqbufs() //分配buf内存
ccic_vidioc_querybuf, //把ccic_vidioc_reqbufs中分配的数据缓存转换成物理地址
ccic_vidioc_qbuf() //把缓冲放回缓存队列
ccic_vidioc_dqbuf() //把数据从缓存中读取出来
ccic_vidioc_streamon() //开始视频显示函数
ccic_vidioc_streamoff() // 结束视频显示函数
ccic_vidioc_queryctrl() //对应调用ov5640_mipi_queryctrl()的接口,功能见上一章
ccic_vidioc_g_ctrl() //对应调用ov5640_mipi_ g_ctrl ()的接口,功能见上一章
ccic_vidioc_s_ctrl() //对应调用ov5640_mipi_ s_ctrl ()的接口,功能见上一章
ccic_vidioc_cropcap() //预留接口,查询驱动的修剪能力
ccic_vidioc_g_register() //对应调用ov5640_mipi_g_registe ()的接口,功能见上一章
ccic_vidioc_s_register() //对应调用ov5640_mipi_ s_register()的接口,功能见上一章
Camera视频数据流流动有如下主要相关函数:
ccic_vidioc_reqbufs() //分配部份内存
ccic_vidioc_querybuf, //把ccic_vidioc_reqbufs中分配的数据缓存转换成物理地址
ccic_vidioc_qbuf() //把缓冲放回缓存队列
ccic_vidioc_dqbuf() //把数据从缓存中读取出来
ccic_irq() //ccic中断处理函数
ccic_v4l_poll, //files poll 功能对于接口
check_jpeg_header //检测抓取数据是否为jpeg文件
具体数据如何流动,见下图:(来自marrvel提供的PXA920 CCIC sensor bring up guide.pdf)
说明:VIDIOC_QBUF对应函数ccic_vidioc_qbuf()
VIDIOC_QBUF对应函数ccic_vidioc_dqbuf()
Dma_map_page //将dma buffer 数据映射到kernel内存空间