(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 failint 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格式。摄像头的分辨率远大于手机LCD屏幕的分辨率,所以在屏幕上显示的一定是经过压缩的图像,拍成的图片则是完全体现摄像头的捕捉画面。高分辨率 的摄像头处理图像时,并不需要划分图像大小的内存,因为那将需要很大的的空间,只需要分段对图像在内存中处理即可。

那么SENSOR的输出有YUV/RGB/RAW/JPEG,这些到底是什么差别呢?

  • YUV:是亮度(Y)+色度(UV)的格式,常用的是YUV422,即数据格式是按Y-U-Y-V输出的。
  • RGB:传统的红绿蓝格式,比如RGB565,一个像素2B。
  • RAW:SENSOR的每一像素对应一个彩色滤光片,每一个像素(单独的R/G/B)直接输出,占1B。
  • JPEG:有些SENSOR带压缩engine,直接输出压缩后的JPEG格式。

另外,摄像头的输出到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桩实现用。

知晓这个流程后,在解决一些问题时就可以有多个思路。比如人眼识别在后台运行时,打开前置或者手电筒有时就出现“无法连接”的问题,这是由于摄像头设备资 源被抢占的问题导致的,而这个问题按正常流程是很难解决掉。考虑到人眼识别的检测周期很短,大概两三百毫秒,可以在OPEN的C++实现地方,加上延时处 理后再重打开。这样,就可以解决“无法连接”的问题。具体是:

android_hardware_Camera.cpp (frameworks\base\core\jni)中的android_hardware_Camera_native_setup函数,加上...int cnt = 20; retry: sp<Camera> camera = Camera::connect(cameraId);if (camera == NULL) {     if (cnt-- > 0)     {         usleep(100 * 1000);        ALOGV("android_hardware_Camera_native_setup, retry cnt=%d", cnt);         goto retry;     }}...

(7)调试摄像头时碰到打开摄像头偶有失败,或者切换前后摄像头失败,这时需要看看摄像头的上电或者掉电时序。另外,造成前后摄像头失效的另一个可 能原因是:摄像头的复位和供电脚默认要内部上拉(根据实际需要),这个是通过实验判断出来的,之前易出问题的手机在把供电和复位接上外接上拉后即OK,在不改变硬件电路的前提下,置成默认内部上拉即解决问题。

摄像头的I2C也是易出问题的部分,之前一直以为前置不需要复位,结果一直有前置的I2C报错,再配上复位脚让前置工作正常后,该问题解决。

如果程序在一开机检测到两个摄像头,那么摄像头调用就会提示前后切换;如果检测不到两个则不提供此切换图标,实现的位置在camera.java:

if (mNumberOfCameras > 1) {    menu.add(R.string.switch_camera_id).setOnMenuItemClickListener(new OnMenuItemClickListener() {     public boolean onMenuItemClick(MenuItem item) {         CameraSettings .writePreferredCameraId( mPreferences, ((mCameraId == mFrontCameraId)       ? mBackCameraId : mFrontCameraId));       onSharedPreferenceChanged();       return true;         }     }).setIcon(android.R.drawable.ic_menu_camera); }

对于APP中是否有检测到两个,可以通过mNumberOfCameras的值来获知。

(8)曾经碰到一个现象:前后置摄像头来回切时,偶尔切到后置会倒像,最后发现是后置摄像头的初始化CLOCK设定有关系,跟镜像寄存器/帧缓冲叠 层都没有关系。关于倒像有两个问题需要说明,比如仅QQ视频时倒像或偏转,一般要通过调试摄像头方向寄存器来解决,通过HAL参数虽然有时可以解决倒像问 题,但是不是所有的应用软件倒像都可以通过这种方式解决。摄像头硬件LAYOUT的方向也决定了图像的预览效果,根据摄像头的扫描方向,如果 480X640的摄像头对应480X320的LCD,这样长宽比都反过来的情况下,在LCD上呈现出来的预览图像是经过处理的,图像会偏大。

(9)预览跟摄像模式在分辨率、帧率等上都有差别,由于摄像模式的帧率较快,曝光时间较短,所以一般画面会暗于预览模式。所以帧率一般只能调到合适位置,帧率太慢预览会有拖尾,帧率太快则会导致曝光时间太短画面偏暗。

(10)关于AF(自动对焦)的问题,通过AF可以调节镜头的焦距到最好位置,从而得到满意清晰度的画面,同时画面亮度会有一定的变化(但是一次以 上的变化是BUG现象)。在拍近距离画面时,AF的变化距离最大,所以一般会耗时久点,甚至可以听到AF工作时的“啪”声。拍暗处画面,由于需要足够的光线来处理,AF的耗时会较光亮时画面偏长 。

如果是RAW sensor的话,对焦是BaseBand这边做的,要外挂AF。如果是YUV sensor的话,要看sensor本身对AF的支持情况。有些YUV senso根本不支持自动对焦,有些sensor只支持单步对焦(对应菜单auto),有些YUVsensor既支持单步对焦也支持连续对焦。

需要向sensor的vendor了解,使用的sensor是否内嵌lens的driver IC,内嵌lens driver ic即直接操作sensor的寄存器去推lens;若sensor没有内嵌lens的driver IC,则需要向模组厂了解,模组是否外挂了lens的driver IC,driver IC的型号是什么。

更多相关文章

  1. Android(安卓)NestedScrolling解决滑动冲突问题(2) - fling问题
  2. Android解决Java.util.concurrent.ExecutionException: com.Andr
  3. 安装android apk包/adb shell的常见问题及解决
  4. android N编译
  5. Android滑动事件冲突解决 Touch事件处理机制
  6. android.view.WindowLeaked的解决办法 has leaked window androi
  7. Android(安卓)ButterKnife导入使用出错解决
  8. android Run模式也会出现"Waiting for debugger"的解决方法
  9. Android音频系统学习笔记

随机推荐

  1. Android(安卓)HTTP框架Volley详解
  2. android studio3 多渠道打包及编译速度优
  3. Android(安卓)basic1
  4. Android平板获取唯一标识DeviceId
  5. Android(安卓)basic1
  6. Android(安卓)自带图标库 android.R.draw
  7. rock960 android box compiling!
  8. android对话框的使用
  9. Android(安卓)自带图标库 android.R.draw
  10. android 6 sdk/ndk下载地址