camera调试过程借鉴

在android的模拟器上面调用系统的摄像机会出现异常的现象,会自动退出,这可能和模拟器有关,模拟器无法使用系统的硬件,就像重力感应和方向感应系统一样都无法使用,甚至是GPS

导航系统也无法使用,好像有个第三方的组织,已经模拟出来模拟器上使用重力感应。但是我没有真正的看到,下面的这几段是一本书上面写的android上面使用模拟器的例子。

这个示例将显示预览图像,在图像上点击则触发拍照操作,拍照成功后显示所拍的照片,然后点击Start菜单可以继续拍照。

首先通过OPhone开发工具(ODT)创建一个OPhone项目,填写基本信息后ODT会自动创建一个\src\org\goodev\camera\CameraActivity.java文件和res\layout\main.xml文件。

把main.xml文件内容修改为如下:

view plaincopy to clipboardprint?

1.    <?xml version="1.0" encoding="utf-8"?>  

2.    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  

3.        android:orientation="vertical"  

4.        android:layout_width="fill_parent"  

5.        android:layout_height="fill_parent"  

6.        >  

7.        <SurfaceView android:id="@+id/camera"  

8.            android:layout_width="fill_parent"  

9.            android:layout_height="fill_parent"/>  

10.     <ImageView android:id="@+id/image"  

11.         android:layout_width="fill_parent"  

12.         android:layout_height="fill_parent"/>  

13. </LinearLayout>  

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <SurfaceView android:id="@+id/camera" android:layout_width="fill_parent" android:layout_height="fill_parent"/> <ImageView android:id="@+id/image" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </LinearLayout>

SurfaceView 用来预览图像,ImageView 用来显示所拍的照片。这里也需读者会问,为什么要使用SurfaceView 来预览图像?使用其他的View不可以吗?要回答这个问题,需要了解下SurfaceView 的作用,关于SurfaceView 的详细介绍已超出了本教程的范围,我们会在后续教程中来详细介绍SurfaceView ,这里只做简要介绍。

在通常情况下,OPhone程序中的View都是在同一个GUI线程中绘制的,该线程也是接收用户交互事件的线程(例如:按钮点击事件)。从另外的线程修改GUI元素是不可以的,如果要迅速的更新UI显示该如何办?显然在主线程中还需要处理其他事件,不适合做这件事情,所以OPhone提供了SurfaceView 来满足这种需求。一个SurfaceView 包装一个Surface对象(通过SurfaceHolder操作该对象)而不是Canvas对象,这就是关键所在,Surface可以在其他线程中绘制,这对于周期性更新和要求高帧率的场景来说是很有用的,特别是在游戏开发中。Surface中包含了当前UI的原生数据(raw data),在不同的软件和硬件条件下对这些数据的处理是不一样的,这就可以通过一些设置来加速图形的绘制,可以通过SurfaceHolder的setType函数来设置,目前接收如下的参数:

·         SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface

·         SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface

·         SURFACE_TYPE_GPU:适用于GPU加速的Surface

·         SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。如果在这里设置了上面三种类型则可以发现不会出现预览图像,在和Camera底层的预览机制实现有关,如果对预览有特殊要求的可以现实PreviewCallback 接口来自己处理。

关于SurfaceView先简单介绍到这里,下面来继续看看如何在代码中实现。

修改CameraActivity类使其实现如下接口:

view plaincopy to clipboardprint?

1.    android.view.SurfaceHolder.Callback   

2.    android.view.View.OnClickListener  

原创 android 之摄像头 

google查了一下camera方面的资料,前几页的检索内容居然一模一样的,真是浪费时间,严重鄙视一下。

既然要用到硬件肯定要牵涉到权限,

在         中加入camera的权限:

<uses-permission android:name="android.permission.CAMERA"></uses-permission>

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

调用camera最简单的办法是调用系统的功能,然后通过onActivityResult方法获得图像数据。

不是太习惯用androidxml配置文件,但是为了代码简单,先加一个layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView android:text="Camera Demo" android:id="@+id/TextView01"
        android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView>
    <RelativeLayout android:id="@+id/FrameLayout01" android:layout_weight="1"
        android:layout_width="fill_parent" android:layout_height="fill_parent"></RelativeLayout>
    <Button android:text="test" android:id="@+id/Button01"
        android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"></Button>
</LinearLayout>

系统camerauri为:

android.media.action.IMAGE_CAPTURE

final int TAKE_PICTURE = 1;
ImageView iv;

private void test1(){

      iv = new ImageView(this);

      ((FrameLayout)findViewById(R.id.FrameLayout01)).addView(iv);

      Button buttonClick = (Button)findViewById(R.id.Button01);

      buttonClick.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View arg0) {
                startActivityForResult(new Intent("android.media.action.IMAGE_CAPTURE"), TAKE_PICTURE);
            }
            
        });

}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == TAKE_PICTURE) {
            if (resultCode == RESULT_OK) {
                Bitmap b = (Bitmap) data.getExtras().get("data");
                iv.setImageBitmap(b);
            }
        }
}

系统功能很简单,呵呵,不过不能满足俺小小的控制欲,看看camera类能干些什么。

首先扫描了一下camera,感觉camera主要是用到几个接口:

1.需要SurfaceHolder类来显示图像,并获取SurfaceHolder类传递给Camera,Camera以后通过该Holder对图像进行处理。

所以程序中需要SurfaceView子类,并实现SurfaceHolder.Callback 接口:

   public void surfaceChanged(SurfaceHolder holder, int format, int width,int height)

   public void surfaceCreated(SurfaceHolder holder)

   public void surfaceDestroyed(SurfaceHolder holder)

如:public class Preview extends SurfaceView implements SurfaceHolder.Callback

2.拍摄相片主要用到如下方法:

public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)

方法中的参数是几个回调接口:

①ShutterCallback

   void onShutter();

拍照时调用该接口,用于按下拍摄按钮后播放声音等操作 

②PictureCallback

   void onPictureTaken(byte[] data, Camera camera);

拍照时调用该接口,data为拍摄照片数据,cameraCamera类自身

takePicture方法中有两个PictureCallback,看参数名好像一个是原始数据,一个是jpeg数据。

3.还有一个预览方式

PreviewCallback

   void onPreviewFrame(byte[] data, Camera camera);

该接口可以获取摄像头每一帧的图像数据

此外此外还有几个辅助方法:

startPreview()
stopPreview()
previewEnabled()

4.其它方法:

①自动对焦 AutoFocusCallback

   void onAutoFocus(boolean success, Camera camera); 

摄像头自动对焦,success表示自动对焦是否成功

② ErrorCallback

   void onError(int error, Camera camera)

摄像头发生错误是调用该接口,

CAMERA_ERROR_UNKNOWN

CAMERA_ERROR_SERVER_DIED 表示媒体服务已经当掉,需要释放Camera重新启动

③setParameters(Parameters params)

设置摄像头参数

先来做一个最简单的测试:

用来表现图像的SurfaceView子类,Android的例子里面有一个,直接拿过来用用:

class camerView extends SurfaceView implements SurfaceHolder.Callback{
    SurfaceHolder mHolder;
    Camera mCamera;
    
    public camerView(Context context) {
        super(context);
        
        mHolder = this.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(width, height);
        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }

    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();
        try {
           mCamera.setPreviewDisplay(holder);
        } catch (IOException exception) {
            mCamera.release();
            mCamera = null;
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
    
    public void draw(Canvas canvas){
        super.draw(canvas);
        Log.d("===>", "draw");
    }
}

内容比较简单,Camera的管理都跟camerView 的几个接口绑在一块。

下来把View加到Active中去,同时用用 takePicture方法:

private void test2(){
    cv = new camerView(this);
    RelativeLayout relay = (RelativeLayout)findViewById(R.id.FrameLayout01);
    relay.addView(cv);
    
    buttonClick = (Button)findViewById(R.id.Button01);
    buttonClick.setOnClickListener(new OnClickListener(){
        public void onClick(View arg0) {
            cv.mCamera.takePicture(
                    new ShutterCallback(){
                        public void onShutter() {
                            Log.d("===>", "onShutter");
                        }},
                    new PictureCallback(){
                        public void onPictureTaken(byte[] data, Camera camera) {
                            Log.d("===>", "raw:" + (data == null ? "null" : data.length));
                        }},//raw
                    new PictureCallback(){
                        public void onPictureTaken(byte[] data, Camera camera) {
                            Log.d("===>", "postview:" + (data == null ? "null" : data.length));
                        }}, //postview
                    new PictureCallback(){
                        public void onPictureTaken(byte[] data, Camera camera) {
                            Log.d("===>", "jpeg:" + (data == null ? "null" : data.length));
                        }} // jpeg
                );
        }
  });

这样所有的代码就完成了,在模拟器上点击test按钮,在log中可以看到:

===>onShutter

===>raw:null

===>jpeg:18474

很奇怪的是 camerView中的 ===>draw没有输出,说明View不进行绘制,那么摄像图像是怎么出来的呢?

源代码中是调用本地方法,懒得去看C代码,不想钻得太深,娱乐而已。

上网查了一半天也没有搞明白,感觉是通过SurfaceHolder获得ViewCanvas对象,直接进行绘制,Holder中没有View的引用,当然不会再去调用Viewdraw方法了。

最后在网上搜到文章一篇,对这个原因有一点说明,Copy之,以防后面忘记:

在通常情况下,OPhone程序中的View都是在同一个GUI线程中绘制的,该线程也是接收用户交互事件的线程(例如:按钮点击事件)。从另外的 线程修改GUI元素是不可以的,如果要迅速的更新UI显示该如何办?显然在主线程中还需要处理其他事件,不适合做这件事情,所以OPhone提供了 SurfaceView 来满足这种需求。一个SurfaceView 包装一个Surface对象(通过SurfaceHolder操作该对象)而不是Canvas对象,这就是关键所在,Surface可以在其他线程中绘 制,这对于周期性更新和要求高帧率的场景来说是很有用的,特别是在游戏开发中。Surface中包含了当前UI的原生数据(raw data),在不同的软件和硬件条件下对这些数据的处理是不一样的,这就可以通过一些设置来加速图形的绘制,可以通过SurfaceHolder的 setType函数来设置,目前接收如下的参数:

SURFACE_TYPE_NORMAL :用RAM缓存原生数据的普通Surface
SURFACE_TYPE_HARDWARE :适用于DMA(Direct memory access )引擎和硬件加速的Surface
SURFACE_TYPE_GPU :适用于GPU加速的Surface
SURFACE_TYPE_PUSH_BUFFERS :表明该Surface不包含原生数 据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数 据,这样图像预览会比较流畅。如果在这里设置了上面三种类型则可以发现不会出现预览图像,在和Camera底层的预览机制实现有关,如果对预览有特殊要求 的可以现实PreviewCallback 接口来自己处理 。

如果想在图像上叠加一些文字等透明信息的时候,总不能也像j2me一样地处理吧。

后面看到一篇文章介绍,直接将一个View叠加到Camera上就可以了,开始还不相信,后面实在找不到其它办法,试一试看看:

test2()中加入

    TextView tv = new TextView(this);
    tv.setText("test");
    
    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    lp.addRule(RelativeLayout.CENTER_IN_PARENT);
    relay.addView(tv, lp);

果然可以。呵呵,分了一下神,再回来看看Camera

既然jpeg数据有输出,看看jpeg是什么内容,

new PictureCallback(){

  public void onPictureTaken(byte[] data, Camera camera) {
      Log.d("===>", "jpeg:" + (data == null ? "null" : data.length));
  }} // jpeg

jpeg的回调接口中添加内容

Log.d("===>", "jpeg:" + (data == null ? "null" : data.length));
cv.setVisibility(View.INVISIBLE);
ImageView iv = new ImageView(test.this);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);  
iv.setImageBitmap(bitmap);
relay.addView(iv); 

其中的test是类名,另外需要把relay改成final变量:

final RelativeLayout relay = (RelativeLayout)findViewById(R.id.FrameLayout01);

呵呵,又看到那幅熟悉的图片了,帅。

raw数据没有输出,网上也有人提问,外网被屏蔽了看不到详细的信息,那就此处不表下次再说了。

看看能不能设置一下参数就可以有输出了,在好奇的驱使下,又试了一下设置参数。

log中可以看到Parameters预设的参数:

picture-format=jpeg
picture-preview=yuv422sp
很可惜,设置为其它的参数系统都报错,玩不转,郁闷,看来要在摄像头这一块抱太多的遗憾了。

算了,看看Camera最后一点功能吧,获取帧数据:

mCamera.setPreviewCallback(new PreviewCallback(){
    public void onPreviewFrame(byte[] data, Camera camera) {
        Log.d("===>", "onPreviewFrame");
    }
});

其中的datayuv格式的,需要对其解码:

static public void decodeYUV420SP(byte[] rgbBuf, byte[] yuv420sp, int width, int height) {
    final int frameSize = width * height;
        if (rgbBuf == null)
            throw new NullPointerException("buffer 'rgbBuf' is null");
        if (rgbBuf.length < frameSize * 3)
            throw new IllegalArgumentException("buffer 'rgbBuf' size "
             + rgbBuf.length + " < minimum " + frameSize * 3);

        if (yuv420sp == null)
            throw new NullPointerException("buffer 'yuv420sp' is null");

         if (yuv420sp.length < frameSize * 3 / 2)
            throw new IllegalArgumentException("buffer 'yuv420sp' size " + yuv420sp.length
              + " < minimum " + frameSize * 3 / 2);

     int i = 0, y = 0;
     int uvp = 0, u = 0, v = 0;
     int y1192 = 0, r = 0, g = 0, b = 0;

     for (int j = 0, yp = 0; j < height; j++) {
          uvp = frameSize + (j >> 1) * width;
          u = 0;
          v = 0;
         for (i = 0; i < width; i++, yp++) {
              y = (0xff & ((int) yuv420sp[yp])) - 16;
             if (y < 0) y = 0;
             if ((i & 1) == 0) {
                  v = (0xff & yuv420sp[uvp++]) - 128;
                  u = (0xff & yuv420sp[uvp++]) - 128;
              }

              y1192 = 1192 * y;
              r = (y1192 + 1634 * v);
              g = (y1192 - 833 * v - 400 * u);
              b = (y1192 + 2066 * u);

             if (r < 0) r = 0; else if (r > 262143) r = 262143;
             if (g < 0) g = 0; else if (g > 262143) g = 262143;
             if (b < 0) b = 0; else if (b > 262143) b = 262143;

              rgbBuf[yp * 3] = (byte)(r >> 10);
              rgbBuf[yp * 3 + 1] = (byte)(g >> 10);
              rgbBuf[yp * 3 + 2] = (byte)(b >> 10);
          }
      }
    } 
摄像头这一块android虽然给了一个接口,但是实现还是各个厂家自己实现的,所以不同的机型处理方式还不一致,

android camera 源码分析(基于应用) 

这里主要是针对Ophone进行介绍的,当然 结合了android的源码(以下出现均为android2.2源码)。 

首先在Ophone中也是通过android.hardware.Camera类来控制摄像头设备的,要使用只有通过 android.hardware.Camera.open()来打开。 try { mCameraDevice = android.hardware.Camera.open(); } 

catch (RuntimeException e) { Log.e(TAG, "fail to connect Camera", e); 

throw new CameraHardwareException(e); } 

另外Ophone还提供了一些接口来给予回调,控制Camera的状态,

分别是: 1.android.hardware.Camera.ErrorCallback:摄像头出错的时候调用,这个接口具有一个void onError(int error,Camera camera)函数;其中,

前者表示数据类型,取值是Camera类中的常量CAMERA_ERROR_UNKNOWN或者是 CAMERA_ERROR_SERVICE_DIED

前者是不明错误,后者是表示服务已经关闭,

在这种情况下需要释放当前的Camera对象,然后再初始化一个。 

private static final class ErrorCallback implements android.hardware.Camera.ErrorCallback { public void onError(int error, android.hardware.Camera camera) { if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) { mMediaServerDied = true; Log.v(TAG, "media server died"); } } } 

2.android.hardware.camera.PreviewCallback:在图像预览时调用,这个接口有一个void onPreviewFrame(byte[] data,Camera camera);参数data为每帧图像的数据流。我们可以根据实际需要来实现这个接口。

3.android.hardware.Camera.ShutterCallback:在图像预览的时候调用,这个接口具有一个void onShutter();可以在改函数中通知用户快门已经关闭,例如播放一个声音。 private final class ShutterCallback implements android.hardware.Camera.ShutterCallback { public void onShutter() { mShutterCallbackTime = System.currentTimeMillis(); mShutterLag = mShutterCallbackTime - mCaptureStartTime; Log.v(TAG, "mShutterLag = " + mShutterLag + "ms"); clearFocusState(); } } 

4.android.hardware.Camera.PictureCallback:当拍摄相片的时候调用,该接口具有一个void onPictureTaken(byte[] data,Camera camera)函数;参数和预览的一样。在android中主要有三个类实现了这个接口,分别是PostViewPictureCallback、 RawPictureCallbackJepgPictureCallback。我们可以根据需要定义自己需要的类。 

5.android.hardware.Camera.AutoFocusCallback:当自动对焦时候调用,该接口具有一个void onAutoFocus(boolean focused,Camera camera)函数

private final class AutoFocusCallback implements android.hardware.Camera.AutoFocusCallback { public void onAutoFocus(boolean focused, android.hardware.Camera camera) { mFocusCallbackTime = System.currentTimeMillis(); 

mAutoFocusTime = mFocusCallbackTime - mFocusStartTime; Log.v(TAG, "mAutoFocusTime = " + mAutoFocusTime + "ms"); 

if (mFocusState == FOCUSING_SNAP_ON_FINISH) { // Take the picture no matter focus succeeds or fails. No need // to play the AF sound if we're about to play the shutter // sound. if (focused) { mFocusState = FOCUS_SUCCESS; } 

else { mFocusState = FOCUS_FAIL; } mImageCapture.onSnap(); } 

else if (mFocusState == FOCUSING)

{ // User is half-pressing the focus key. Play the focus tone. // Do not take the picture now. ToneGenerator tg = mFocusToneGenerator; if (tg != null) 

{ tg.startTone(ToneGenerator.TONE_PROP_BEEP2); } 

if (focused) { mFocusState = FOCUS_SUCCESS; } 

else { mFocusState = FOCUS_FAIL; } } 

else if (mFocusState == FOCUS_NOT_STARTED)

{ // User has released the focus key before focus completes. // Do nothing. } updateFocusIndicator(); } } 

6.还提供了放大缩小的监听器android.hardware.Camera.OnZoomChangeListener

private final class ZoomListener implements android.hardware.Camera.OnZoomChangeListener { public void onZoomChange(int value, boolean stopped, android.hardware.Camera camera) { Log.v(TAG, "Zoom changed: value=" + value + ". stopped=" + stopped); mZoomValue = value; // Keep mParameters up to date. We do not getParameter again in // takePicture.

If we do not do this, wrong zoom value will be set. mParameters.setZoom(value); 

// We only care if the zoom is stopped. mZooming is set to true when 

// we start smooth zoom.

if (stopped && mZoomState != ZOOM_STOPPED)

{ if (value != mTargetZoomValue) { mCameraDevice.startSmoothZoom(mTargetZoomValue); mZoomState = ZOOM_START; } 

else { mZoomState = ZOOM_STOPPED; } } } } 

当取得照片的数据流后可以通过BitmapFactorydecodeByteArray()函数来解析图片。 

另外还可以通过Camera对象的getParameters()函数来得到一个android.hardware.Camera.Parameters 对象,Parameters提供了一些接口来设置Camera的属性:

1.setPictureFormat(int pixel_format):设置图片的格式,其取值为PixelFormat YCbCr_420_SPPixelFormatRGB_565或者PixelFormatJPEG。 

2.setPreviewFormat(int pixel_format):设置图片的预览格式,取值如上。

3.setPictureSize(int width,int height):设置图片的高度和宽度,单位为像素。

4.setPreviewSize(int width,int height):设置预览的高度和宽度,取值如上。

5.setPreviewFrameRate(int fps):设置图片预览的帧速。 在设置好Camera的参数后,可以通过函数void startPreview()开始预览图像、void stopPreview()结束预览,通过autoFocus(AutoFocusCallback cb)来自动对焦,最后可以通过takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)函数来拍照。

该函数有三个参数,分别为快门回调接口、原生图像数据接口和压缩格式图片数据接口。

如果数据格式不存在的话数据流为空,如果不需要实现这些接口则这些参数取值可以为null

Android平台硬件调试之Camera篇 

    之前一段时间有幸在高通android平台上调试2camera sensor,一款是OV5M YUV sensor,支持jpeg out,同时也支持AF,调试比较比较简单,因为别的项目已经在使用了,只是把相关的驱动移植过来就好;另一款是Samsung的一款比较新的3M YUV FF sensor,在最新项目中要使用的,本文以调试该sensor为例,从底层驱动的角度分享一下高通android平台下调试camera的经验,而对于高通平台camera部分的架构以及原理不做过多的介绍。
    一、准备工作
    从项目中看,在硬件(板子)ready前,软件部分是要准备好的。单独从底层驱动来看,软件部分可以分为2个部分,一个是高通平台相关的,再一个就是 sensor部分的,通常的做法就是把sensor相关的设定移植到高通平台的框架之中。这样就需要先拿到sensorspec以及厂商提供的 sensor register setting fileSpec的用途是清楚高通平台和sensor通讯(读写寄存器)的时序以及相关参数设定;而厂商提供的setting file则是在使用camera各个功能(previewsnapshot...)时候需要写入到sensor中的.
    本项目中,高通平台为MSM7X27cameraSamsung 5CA。从spec中知道,该sensorI2C ID0x78I2C的通信采用双字节方式,另外也弄清楚了读写sensor寄存器的规则,从调试角度看这些基本上够用了。另外厂商提供的 setting file,其实就是寄存器列表,告诉我们再什么时候将哪些寄存器写入什么值,通常是一个寄存器地址再加上一个寄存器的值,不过Samsung提供的是PC 上调试使用的文本,需要自己转换成c语言中的二维数组。从文件中看,寄存器数据可以分为几个部分:初始化、IQ设定(tuning相关)、clk设定、 preview设定、snapshot设定,基本上有这几个就够了,其他的比如调节亮度啦、设定特殊效果啦、设置白平衡啦等等都可以自己通过spec来完成。
    Sensor部分的东西搞定后,接下来就是修改高通camera部分的驱动了,主要有:
Kernal部分:
1、检查Sensor的电源配置,并修改软件中的设定。本项目中使用2.8/1.8/1.53个电源。
2、检查并修改sensor reset设置。注意reset的时间设定,务必和spec中一致,否则会导致sensor无法工作。
3修改I2C驱动,使用双字节读写的接口,并完成读取sensor ID的接口。这个用来检验I2C通讯是否OK
4、导入寄存器设定,分别在初始化、previewsnapshot等几个部分写入对应的寄存器值。
注意:reset以及写寄存器部分一定要按照spec的规定加入一些delay,否则会导致sensor工作异常

User空间部分:
这个部分主要是根据硬件的规格来配置VFE,如sensor输出数据的格式,接口方式、分辨率大小、同步信号模式等,比较简单,但一定要检查仔细,任何一个地方不对都会导致调试失败。
    到这里为止,软件部分的准备已经告一段落了。

    二、调试环境准备(板子出来了,但sensor sample还没到位)
    首先,测试点的准备。
    调试前就需要想好,如果sensor无法工作,要怎么去debug,这就需要去测量一些信号,比如powerresetI2CM/P CLKH/V同步信号、数据信号等,要确保这些信号都可以测量到。
    其次要选择软件的调试环境,这里选择在ADB环境中执行高通的mm-qcamera-test程序来调试,相关的trace都可以打印出来。
    这样就万事俱备,只欠sensor了。

    三、调试(sensor终于拿到了)
    sensor接到板子上,开机后,ADB中运行调试程序,preview画面并没有出来,失败,有点小失望,本来觉得可以一气呵成的,但毕竟这是一个全新的sensor,任何一个地方没有想到位做到位都会导致失败。那就找原因吧。
    1、首先从trace得知,I2C已经读到了sensorID0x05CA,这可以说明I2C通讯是没有问题的
    2、接着检查Sensor的电源配置,测量了供给sensor3个电源,都是OK的。
    3、测量MCLK,这个是提供给sensor使用的,正常(24MHZ
    4、测量PCLK,这个是sensor输出的,正常(58MHZ,高通上限为96MHZ),和寄存器中配置的一致。
    5、测量H/V同步信号,这个是sensor输出的,正常。和FPS和分辨率一致。
    6、测量数据信号,这个是sensor输出的,正常。(数据信号,示波器上可以看到)
    这样看来,sensor已经在正常工作了,但为何preview画面没有出来呢?继续检查高通这边的设定。
    trace看,高通的VFE已经reset并且start了,但一直接没有输出preview数据,这就奇怪了,sensor明明已经输出了,为什么 VFE接收后并没有把数据吐出来呢,难道这个sensor输出的数据VFE无法识别?为了验证这个问题,我在另一块板子上测量了OV sensor输出数据的波形,主要是M/P clkH/V同步信号,然后再拿来对比,不过并没有发现异常,只是H/V同步信号有所不同,主要高低的占空比不太一致,会不会是这样信号的问题呢?为了进一步验证,我同时测量了H/V 信号和数据信号,这时发现OV sensor输出的数据信号是包在V帧同步信号的低电平中;而Samsung 5CA输出的数据信号是包在V帧同步信号的高电平中,会不会是因为V信号极性设置不对导致VFE没有读取到sensor输出的数据呢?重新检查了一下高通 VFE的设定,果然有一个参数是用来设定V信号极性的,这个参数默认是Active Low的,我这边并没有去修改它。接着把这个参数修改为Active High,重新builddownload后,开机运行,Ok了,preview画面可以正常显示了。到这里为止sensor的硬件调试可以算作完成了,后续的其他功能也可以慢慢完善了。
    NoteV同步即帧同步信号,代表一帧数据的开始,VFE会根据该信号来读取一帧数据。
              H同步即行同步信号,代表一行数据的开始,VFE会根据该信号来读取一行数据。H信号一定是包在V同步中的。



转载于:https://www.cnblogs.com/yuzaipiaofei/archive/2011/08/15/4124377.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值