转载:http://blog.csdn.net/zhandoushi1982/article/details/5019860
各种款式的摄像头会有一个最大的支持分辨率,通常此时的格式约定是:1,30W:640*480=307200;
2,130W:1280*1024=1310720;
3,200W:1600*1200=1920000;
4,300W:2048*1536=3145728;
5,500W:2592*1944=5038848;
6,1600W:4096*4096=16777216;
硬件平台是6410,软件平台是android 。目前调试一颗500W像素摄像头时,计划从低分辨率往高分辨调(ov5642的分辨率寄存器是0x3804/05/06/07)。当在linux内核设置640X480(30W)的camera寄存器组,在android中运行camera程序preview和snapshot都正常。如果在内核设置1280X1024(130W)的寄存器组,android运行camera程序preview就黑屏,并且Logcat会打印:
......
android::fimc_poll(int, pollfd*)::poll(1000) doesnt return
S3C6410Camera::m_readCamera(unsigned char*, unsigned int, unsigned int*, int)::fimc_poll fail
int android::S3C6410CameraHWInterface::m_previewThreadFunc()::m_camera->getPreview fail
......
跟踪代码,发现造成fail的根源在于:函数fimc_poll()中的poll 摄像头事件操作没有成功返回,此时打开摄像头设备也是成功的。程序中的poll时间设置的是1000毫秒。我有试过延时,不过preview仍然黑屏。设想出现poll错误的原因是内核中的camera寄存器值设置的有问题,但我使用的这组值在同样的硬件平台上WIN CE里面是可用的。正常情况下,只要设置不同的camera寄存器值就可以实现输出不同分辨率的ITU656数据给6410。
最终换了个平台后解决,可能是硬件问题引起,这证明俺的软件做法是没问题的。一个调试方法是可以写入6410的寄存器值(规格书670页TestPattern寄存器)保证其产生内部自带的彩条信号,通过回显和对比图片来判断现象。
**********************************************************************************
后来发现拍照图片还有偏绿的现象,preview颜色正常,但是拍照的瞬间蒙了层绿色,结果保存到电脑的相片也成绿色。一开始怀疑是camera寄存器的问题,查找OV5642的规格书,将涉及到绿色的若干寄存器值改小,拍照偏绿无法改善。后来怀疑是不是拍照片时图像的YUV空间跟照片的YUV空间不一致所致,将preview和Jpeg的初始化格式参数改成一致,并且改动了android图片保存的语句,仍然无法解决,期间考虑到图片保存格式和内存分配不一致的可能。
最终确认是拍完照后重新进入Preview后又一次载入了全部寄存器,而此时的状态跟启动camera软件时的状态是类似的,处于自动调整时不稳定的状态,capture此时恰好抓到了此时的相片所以偏绿。改动主要在初始化载入一次全部寄存器即可,如果运行时要改动分辨率,只需要改动相关的寄存器就可以,不需要全部载入。
****************************************************************************************
解决的另一个BUG是:摄像头驱动设置5M像素时,拍照无法保存图片。根据它此时的打印信息:
pmem: could not find allocation for map.等导致cupcake的create pmem,yuv2jpg等函数全部错误。此时添加打印语句:发现要求的内存空间跟可分配的空间大小不一致,具体就是不够用。于是改动相关参数如下:
(1)reserved_mem.h中
#define RESERVED_MEM_MFC (12*1024*1024)//(4 * 1024 * 1024)
#define RESERVED_PMEM_PREVIEW (12* 1024 * 1024)
(2)cupcake中的m_pictureThreadFunc函数
//if(m_createPmem(PMEM_JPEG_DEV_NAME, snapshot_size, 1) < 0)
if(m_createPmem(PMEM_JPEG_DEV_NAME, 12*1024*1024 , 1) < 0)
(3)在cupcake中设定保证preview和snapshot的分辨率要一致,且跟内核驱动的具体分辨率一致。
这样就解决了500W像素不能保存图片的问题。
*****************************************************************************************
还存在的一个BUG是:拍照后在LCD上回显照片时,全是白屏。只需要改大另一个PMEM大小:
#define RESERVED_PMEM_RENDER (24* 1024 * 1024)//(8* 1024 * 1024)即可
*****************************************************************************************
补充raw跟YUV格式的差别:前者是没有处理过的数据,后者则是处理过的。高像素一般都是 RAW格式,YUV 是SENSOR 自己的ISP处理的,RAW 的话要交给AP处理。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
补充一点关于WINCE平台的同行经验:
WINCE平台的camera部分,分成preview和cocec两部分。采用标准的流接口驱动,弄CE的应该都很熟悉了。其中以CamInit这个函数最为重要,这个函数把preview和Codec模式下的配置参数都设置好,其中最容易出错的地方就是DMA缓存大小的设置,在Camif.h文件里有两个宏:#define Preview_Mem_Size 352*288*2*4 ,#define Codec_Mem_Size 1280*1024*3/2。这个一定要跟CamInit函数里的相关地方对应。
另外在Virtual_Alloc这个函数里申请了DMA缓存,Pre和Codec有各自的缓存,一定不要弄混了,Display_Cam_Image函数是用来在Pre模式下实时显示的,这个比较简单,就是把数据直接拷贝到显示缓存里就行了,Copy_Cam_Image函数是用来在Codec模式下捕获一帧数据的,CameraCaptureThread这个线程就是用来完成工作的,开中断,关中断都是在这里面实现的。