android Camera API1+HAL1 StartPreview流程 & Android M

上一篇文章android Camera API1+HAL1 open camera流程 & Android M已经跟踪了open camera在framework层的整个流程,这篇文章主要分析StartPreview的流程。

很多博主分析camera流程的相关流程都是从java接口层一鼓作气分析到hal层,这样分析的好处是流程连贯。但整个分析流程则非常长,贴上代码的话,文章也变得异常的长,让人望而生畏,失去阅读的欲望。

对hal层的分析对于很多读者来说是不关心的,我打算将framework层和hal层的流程分开分析,framework层各芯片厂商都是一致的,分析的文章也更具普适性。目前分析流程的文章只针对framework层的代码,必要时捎带讲述下hal层的和framework层的接口部分。后续的文章会单独分析下TI 和高通hal层内部流程和架构。

闲言少叙,还是从官方示例开始分析,以下是一段官方示例

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }
    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }
        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }
        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}

打开camera后,我们需要预览画面,这就需要一个surface作为画布,将创建的surface传递到hal层,供hal往surface里填充数据,进而显示camera采集画面。

开始预览之前,需要先设置预览

0 setPreviewDisplay

  • Camera.java
 public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
     if (holder != null) {
         setPreviewSurface(holder.getSurface());
     } else {
         setPreviewSurface((Surface)null);
     }
 }
 public native final void setPreviewSurface(Surface surface) throws IOException;

从SurfaceHolder中获取到一个surface,作为setPreviewSurface的参数传递下去,setPreviewSurface是一个native函数,直接调用到JNI层。

  • android_hardware_Camera.cpp
{ "setPreviewSurface",
  "(Landroid/view/Surface;)V",
  (void *)android_hardware_Camera_setPreviewSurface },
  
static void android_hardware_Camera_setPreviewSurface(JNIEnv *env, jobject thiz, jobject jSurface)
{
    ALOGV("setPreviewSurface");
    sp<Camera> camera = get_native_camera(env, thiz, NULL);
    if (camera == 0) return;
    sp<IGraphicBufferProducer> gbp;
    sp<Surface> surface;
    if (jSurface) {
        surface = android_view_Surface_getSurface(env, jSurface);
        if (surface != NULL) {
            gbp = surface->getIGraphicBufferProducer(); 	0-1
        }
    }
    if (camera->setPreviewTarget(gbp) != NO_ERROR) {		0-2
        jniThrowException(env, "java/io/IOException", "setPreviewTexture failed");
    }
}

Surface(c++层)其实是对IGraphicBufferProducer的一个封装,后续和buffer打交道的其实是Surface类里面的sp mGraphicBufferProducer变量。0-1获取surface内部的IGraphicBufferProducer指针,0-2将该指针传递到native层去。

1 setPreviewTarget

  • Camera.cpp
// pass the buffered IGraphicBufferProducer to the camera service
status_t Camera::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer)
{
    ALOGV("setPreviewTarget(%p)", bufferProducer.get());
    sp <ICamera> c = mCamera;	1-1
    if (c == 0) return NO_INIT;
    ALOGD_IF(bufferProducer == 0, "app passed NULL surface");
    return c->setPreviewTarget(bufferProducer);	1-2
}

1-1处的mCamera是一个BpCamera指针,这在上一篇文章中有交代过,1-2将会调用到ICamera.cpp中去。

  • ICamera.cpp
class BpCamera: public BpInterface<ICamera>
{
public:
// pass the buffered IGraphicBufferProducer to the camera service
status_t setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer)
{
    ALOGV("setPreviewTarget");
    Parcel data, reply;
    data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
    sp<IBinder> b(IInterface::asBinder(bufferProducer));
    data.writeStrongBinder(b);
    remote()->transact(SET_PREVIEW_TARGET, data, &reply);
    return reply.readInt32();
}
---
status_t BnCamera::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
	......
    case SET_PREVIEW_TARGET: {
        ALOGV("SET_PREVIEW_TARGET");
        CHECK_INTERFACE(ICamera, data, reply);
        sp<IGraphicBufferProducer> st =
            interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
        reply->writeInt32(setPreviewTarget(st));
        return NO_ERROR;
    } break;

这部分就是一个常规的Binder RPC调用,代码相对比较简单。上篇文章交代过,CameraClient类继承并实现了BnCamera类,所以此处接下来会调用到CameraClient类中。

  • CameraClient.cpp
// set the buffer consumer that the preview will use
status_t CameraClient::setPreviewTarget(
        const sp<IGraphicBufferProducer>& bufferProducer) {
    LOG1("setPreviewTarget(%p) (pid %d)", bufferProducer.get(),
            getCallingPid());
    sp<IBinder> binder;
    sp<ANativeWindow> window;
    if (bufferProducer != 0) {
        binder = IInterface::asBinder(bufferProducer);
        // Using controlledByApp flag to ensure that the buffer queue remains in
        // async mode for the old camera API, where many applications depend
        // on that behavior.
        window = new Surface(bufferProducer, /*controlledByApp*/ true);  1-3
    }
    return setPreviewWindow(binder, window);
}

1-3利用上层传下来的Surface里的IGraphicBufferProducer新建一个本地Surface实例window,Surface只是一个辅助工具类,后续hal层通过这个新建的window去duqueue 、queue buffer等操作,完成对显示buffer的填充。

status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,
        const sp<ANativeWindow>& window) {
    Mutex::Autolock lock(mLock);
    status_t result = checkPidAndHardware();
    if (result != NO_ERROR) return result;
    // return if no change in surface.
    if (binder == mSurface) {
        return NO_ERROR;
    }
    if (window != 0) {
        result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
        if (result != NO_ERROR) {
            ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
                    result);
            return result;
        }
    }
    // If preview has been already started, register preview buffers now.
    if (mHardware->previewEnabled()) { // 第一次设置setPreview不会走进这里
        if (window != 0) {
            native_window_set_scaling_mode(window.get(),
                    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
            native_window_set_buffers_transform(window.get(), mOrientation);
            result = mHardware->setPreviewWindow(window);
        }
    }
    if (result == NO_ERROR) {
        // Everything has succeeded.  Disconnect the old window and remember the
        // new window.
        disconnectWindow(mPreviewWindow);
        mSurface = binder;		
        mPreviewWindow = window;	1-4
    } else {
        // Something went wrong after we connected to the new window, so
        // disconnect here.
        disconnectWindow(window);
    }

    return result;
}

此setPreviewWindow函数在preview没有enable的时候,只会走进1-4中,将新建的window保存在CameraClient的成员mPreviewWindow中,这一步并没有真正的setPreviewWindow下去。

2. startPreview

java接口层Camera.java中没有定义startPreview函数,只是申明了一下本地定义的public native final void startPreview();接下来直接查看JNI中的相应函数。

  • android_hardware_Camera.cpp
{ "startPreview",
  "()V",
  (void *)android_hardware_Camera_startPreview },

static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
{
    ALOGV("startPreview");
    sp<Camera> camera = get_native_camera(env, thiz, NULL);
    if (camera == 0) return;

    if (camera->startPreview() != NO_ERROR) {
        jniThrowRuntimeException(env, "startPreview failed");
        return;
    }
}
  • ICamera.cpp
class BpCamera: public BpInterface<ICamera>
{
public:
    // start preview mode, must call setPreviewTarget first
    status_t startPreview()
    {
        ALOGV("startPreview");
        Parcel data, reply;
        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
        remote()->transact(START_PREVIEW, data, &reply);
        return reply.readInt32();
    }

status_t BnCamera::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case START_PREVIEW: {
            ALOGV("START_PREVIEW");
            CHECK_INTERFACE(ICamera, data, reply);
            reply->writeInt32(startPreview());
            return NO_ERROR;
        } break;
  • CameraClient.cp
// start preview mode
status_t CameraClient::startPreview() {
    LOG1("startPreview (pid %d)", getCallingPid());
    return startCameraMode(CAMERA_PREVIEW_MODE);
}

// start preview or recording
status_t CameraClient::startCameraMode(camera_mode mode) {
    LOG1("startCameraMode(%d)", mode);
    Mutex::Autolock lock(mLock);
    status_t result = checkPidAndHardware();
    if (result != NO_ERROR) return result;

    switch(mode) {
        case CAMERA_PREVIEW_MODE:
            if (mSurface == 0 && mPreviewWindow == 0) {
                LOG1("mSurface is not set yet.");
                // still able to start preview in this case.
            }
            return startPreviewMode();
     .....
 }
 
status_t CameraClient::startPreviewMode() {
    LOG1("startPreviewMode");
    status_t result = NO_ERROR;
    // if preview has been enabled, nothing needs to be done
    if (mHardware->previewEnabled()) {
        return NO_ERROR;
    }
    if (mPreviewWindow != 0) {
        native_window_set_scaling_mode(mPreviewWindow.get(),
                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
        native_window_set_buffers_transform(mPreviewWindow.get(),
                mOrientation);
    }
    mHardware->setPreviewWindow(mPreviewWindow);	2-1
    result = mHardware->startPreview();				2-2
    if (result == NO_ERROR) {
        mCameraService->updateProxyDeviceState(
            ICameraServiceProxy::CAMERA_STATE_ACTIVE,
            String8::format("%d", mCameraId));
    }
    return result;
}

2-1这里才是真正的设置window到hal层

  • CameraHardwareInterface.h
 /** Set the ANativeWindow to which preview frames are sent */
 status_t setPreviewWindow(const sp<ANativeWindow>& buf)
 {
     ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());

     if (mDevice->ops->set_preview_window) {
         mPreviewWindow = buf;				2-3
         mHalPreviewWindow.user = this;		2-4
         ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,
                 &mHalPreviewWindow, mHalPreviewWindow.user);
         return mDevice->ops->set_preview_window(mDevice,
                 buf.get() ? &mHalPreviewWindow.nw : 0);	2-5
     }
     return INVALID_OPERATION;
 }

2-3将在CameraClient里新建的一个ANativeWindow保存在CameraHardwareInterface内部,不继续传递到hal层去,因为和ANativeWindow相关的dequeue、queue buffer等相关的接口也是在CameraHardwareInterface内部定义的,这是显示方面的接口,这些接口后续会被hal层回调,所以这个ANativeWindow没必要传递到hal层去。

static ANativeWindow *__to_anw(void *user)
{
    CameraHardwareInterface *__this =
            reinterpret_cast<CameraHardwareInterface *>(user);
    return __this->mPreviewWindow.get();		2-6
}
#define anw(n) __to_anw(((struct camera_preview_window *)n)->user)  2-7

static int __dequeue_buffer(struct preview_stream_ops* w,	2-8
                            buffer_handle_t** buffer, int *stride)
{
    int rc;
    ANativeWindow *a = anw(w);
    ANativeWindowBuffer* anb;
    rc = native_window_dequeue_buffer_and_wait(a, &anb);
    if (!rc) {
        *buffer = &anb->handle;
        *stride = anb->stride;
    }
    return rc;
}
static int __enqueue_buffer(struct preview_stream_ops* w,
                  buffer_handle_t* buffer)
{
    ANativeWindow *a = anw(w);
    return a->queueBuffer(a,
              container_of(buffer, ANativeWindowBuffer, handle), -1);
}

2-4将CameraHardwareInterface实例指针保存在其内部struct camera_preview_window mHalPreviewWindow变量的user中,2-5中将mHalPreviewWindow.nw的地址传递到hal层去,nw变量在camera_preview_window结构体里是第一个成员,其地址也就是变量mHalPreviewWindow的地址(上一篇文章也讲述了两处类似的做法)。将这个nw地址传递到hal层,后续hal层回调时在函数实参中依然会带着这个nw的地址(如2-8),这样就方便从中提取mHalPreviewWindow,进一步提取2-4的CameraHardwareInterface实例指针(如2-7)和获取2-3中的mPreviewWindow(如2-6)。

    struct camera_preview_window {
        struct preview_stream_ops nw;
        void *user;
    };
  • hardware/libhardware/include/hardware/camera.h
typedef struct preview_stream_ops {
    int (*dequeue_buffer)(struct preview_stream_ops* w,
                          buffer_handle_t** buffer, int *stride);
    int (*enqueue_buffer)(struct preview_stream_ops* w,
                buffer_handle_t* buffer);
	......
}

继续分析2-2 mHardware->startPreview()

/**
 * Start preview mode.
 */
status_t startPreview()
{
    ALOGV("%s(%s)", __FUNCTION__, mName.string());
    if (mDevice->ops->start_preview)
        return mDevice->ops->start_preview(mDevice);
    return INVALID_OPERATION;
}

这里继续调用到hal层去了,hal层具体的startPreview的内部逻辑是因芯片产商的不同而各异的,在此先不跟踪进去,先点到为止。

至此,framework层的startPreview流程就基本跟踪完了,相对于open camera来说,简单了很多,毕竟这只是一个指令的控制流。

startPreview的流程调用如下图
android Camera API1+HAL1 StartPreview流程 & Android M_第1张图片
android Camera API1+HAL1 StartPreview流程 & Android M_第2张图片
stop preview的流程和start preview的流程大致相同,在此就不分析了,贴上流程图
android Camera API1+HAL1 StartPreview流程 & Android M_第3张图片
在这里插入图片描述
下一篇文章将分析拍照的控制流和数据流的回调

你可能感兴趣的:(camera)