(1)各种款式的摄像头会有一个最大的支持分辨率,通常此时的格式约定是:
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寄存器)保证其产生内部自带的彩条信号,通过回显和对比图片来判断现象。
(2)后来发现拍照图片还有偏绿的现象,preview颜色正常,但是拍照的瞬间蒙了层绿色,结果保存到电脑的相片也成绿色。一开始怀疑是camera寄存器的问题,查找OV5642的规格书,将涉及到绿色的若干寄存器值改小,拍照偏绿无法改善。后来怀疑是不是拍照片时图像的YUV空间跟照片的YUV空间不一致所致,将preview和Jpeg的初始化格式参数改成一致,并且改动了android图片保存的语句,仍然无法解决,期间考虑到图片保存格式和内存分配不一致的可能。
最终确认是拍完照后重新进入Preview后又一次载入了全部寄存器,而此时的状态跟启动camera软件时的状态是类似的,处于自动调整时不稳定的状态,capture此时恰好抓到了此时的相片所以偏绿。改动主要在初始化载入一次全部寄存器即可,如果运行时要改动分辨率,只需要改动相关的寄存器就可以,不需要全部载入。
出现在MTK平台上的拍照瞬间偏绿,是这样引起的:ISP的OB值调整的太多,这些跟摄像头的驱动和HAL参数是没有关系点。
(3)解决的另一个BUG是:摄像头驱动设置5M像素时,拍照无法保存图片。根据它此时的打印信息:
pmem: could not find allocation for map.等导致cupcake的create pmem,yuv2jpg等函数全部错误。此时添加打印语句:发现要求的内存空间跟可分配的空间大小不一致,具体就是不够用。于是改动相关参数如下:
A,reserved_mem.h中
#define RESERVED_MEM_MFC (12*1024*1024)//(4 * 1024 * 1024)
#define RESERVED_PMEM_PREVIEW (12* 1024 * 1024)
B,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)
C,在cupcake中设定保证preview和snapshot的分辨率要一致,且跟内核驱动的具体分辨率一致。
这样就解决了500W像素不能保存图片的问题。
(4)还存在的一个BUG是:拍照后在LCD上回显照片时,全是白屏。只需要改大另一个PMEM大小:
#define RESERVED_PMEM_RENDER (24* 1024 * 1024)//(8* 1024 * 1024)即可
(5)raw跟YUV格式的差别:前者是没有处理过的数据,后者则是处理过的。高像素一般都是 RAW格式,YUV 是SENSOR 自己的ISP处理的。摄像头的分辨率远大于手机LCD屏幕的分辨率,所以在屏幕上显示的一定是经过压缩的图像,拍成的图片则是完全体现摄像头的捕捉画面。高分辨率的摄像头处理图像时,并不需要划分图像大小的内存,因为那将需要很大的的空间,只需要分段对图像在内存中处理即可。
另外,摄像头的输出到CPU,这个过程仅仅是传输和压缩的过程,跟摄像头的输出格式没有任何关系。所以有MIPI,或者并口656的分类。
(6)android中的camera调用大概的流程是:camera app-》CAM JNI-》CameraService::Client-》CameraHardware-》mHalCam,而mHalCam这部分属于厂商自己的HAL层,一般是不会开放源码。具体到代码中,即是:Camera.java (frameworks\base\core\java\android\hardware) -》android_hardware_Camera.cpp (frameworks\base\core\jni)-》CameraService.cpp (frameworks\base\services\camera\libcameraservice) ,再下面的就是厂商自己实现的如mhal,或者用默认的stab桩实现用。
(7)调试摄像头时碰到打开摄像头偶有失败,或者切换前后摄像头失败,这时需要看看摄像头的上电或者掉电时序。另外,造成前后摄像头失效的另一个可能原因是:摄像头的复位和供电脚默认要内部上拉(根据实际需要),这个是通过实验判断出来的,之前易出问题的手机在把供电和复位接上外接上拉后即OK,在不改变硬件电路的前提下,置成默认内部上拉即解决问题。
(8)曾经碰到一个现象:前后置摄像头来回切时,偶尔切到后置会倒像,最后发现是后置摄像头的初始化CLOCK设定有关系,跟镜像寄存器/帧缓冲叠层都没有关系。关于倒像有两个问题需要说明,比如仅QQ视频时倒像或偏转,一般要通过调试摄像头方向寄存器来解决,通过HAL参数虽然有时可以解决倒像问题,但是不是所有的应用软件倒像都可以通过这种方式解决。摄像头硬件LAYOUT的方向也决定了图像的预览效果,根据摄像头的扫描方向,如果480X640的摄像头对应480X320的LCD,这样长宽比都反过来的情况下,在LCD上呈现出来的预览图像是经过处理的,图像会偏大。
(9)预览跟摄像模式在分辨率、帧率等上都有差别,由于摄像模式的帧率较快,曝光时间较短,所以一般画面会暗于预览模式。所以帧率一般只能调到合适位置,帧率太慢预览会有拖尾,帧率太快则会导致曝光时间太短画面偏暗。
(10)关于AF(自动对焦)的问题,通过AF可以调节镜头的焦距到最好位置,从而得到满意清晰度的画面,同时画面亮度会有一定的变化(但是一次以上的变化是BUG现象)。在拍近距离画面时,AF的变化距离最大,所以一般会耗时久点,甚至可以听到AF工作时的“啪”声。拍暗处画面,由于需要足够的光线来处理,AF的耗时会较光亮时画面偏长 。