对于AP层用户,通过Camera界面, 以最直观的方式能够从Camera显示窗口中看到的Camera Display主要包括三部分。各部分的具体细节如下所示。
(1)Camera Preview Display
对于Camera Preview Display, 从Camera应用程序的角度来看,AP层需要实现Android.hardware.Camera(Framework层)类提供给上层应用的preview相关接口,完成相应的逻辑处理。但Preview作为大数据量交换的处理过程,系统不可能通过回调方式,最终将底层Camera硬件设备采集的数据交给AP层来处理。所以,上层应用只需要做一些简单的状态和UI显示处理,AP不需要接收处理真正的Preview数据,而是将数据接收和处理的过程交由ISurface接口来完成,确切的说是由ISurface的实现类SurfaceFlinger来完成。
AP层通过调用android.hardware.Camera类提供的startPreview函数,最终通过libcamera_client.so的Camera类,利用Binder IPC,通知CameraService, CameraService通过调用其内部类Clien,内部类再通过调用HAL层提供的Camera功能完成相应的操作。
CameraService层针对Camera Client端得请求,都将交与其内部类Client来完成。CameraService层的startPreview的具体实现由CameraService::Client类的startPreviewMode函数完成相应的操作。
status_t CameraService::Client::startPreviewMode() { // if preview has been enabled, nothing needs to be done if (mHardware->previewEnabled()) { return NO_ERROR; } // start preview mode status_t ret = NO_ERROR; if (mUseOverlay) { …. } else { mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME); ret = mHardware->startPreview(); if (ret != NO_ERROR) return ret; // If preview display has been set, register preview buffers now. if (mSurface != 0) { // Unregister here because the surface registered with raw heap. mSurface->unregisterBuffers(); ret = registerPreviewBuffers(); } } return ret; } status_t CameraService::Client::registerPreviewBuffers() { int width, height; CameraParameters params(mHardware->getParameters()); params.getPreviewSize(&width, &height); // don't use a hardcoded format here ISurface::BufferHeap buffers(width, height, width, height, PIXEL_FORMAT_RGB_565, mOrientation, 0, mHardware->getPreviewHeap()); status_t ret = mSurface->registerBuffers(buffers); if (ret != NO_ERROR) { LOGE("registerBuffers failed with status %d", ret); } return ret; }
从上面的代码我们可以看到,ISurface为Camera Preview Display专门注册了显示缓冲区,该缓冲区映射到mHardware->getPreviewHeap()指向的内存空间,缓冲区接收的数据格式为PIXEL_FORMAT_RGB_565。
CameraService已经为Camera Preview Display准备好了显示缓冲区,哪谁为注册的这块Buffer填充Preview数据呢?为了完成Camera Preview,Camera HAL层的CameraHardware类提供了previewThread线程,来完成底层数据到ISurface缓冲区的投递。通过线程Loop最终将Camera硬件设备采集的数据不断送到显示缓冲区,最后显示到AP界面上。
int CameraHardware::previewThread() { int width, height; mParameters.getPreviewSize(&width, &height); if (!previewStopped && mPreviewBuffer != 0 && mRawBuffer !=0 && mDataFn) { int delay = (int)(1000000.0f / float(previewFrameRate)); ①mCamera.GrabRawFrame(mHeap->getBase()); if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME){ ②mCamera.GrabPreviewFrame((mHeap->getBase(), mPreviewHeap->getBase()); ③mDataFn(CAMERA_MSG_PREVIEW_FRAME, mPreviewBuffer, mUser); delay-=100; } ……… } return NO_ERROR; }
从代码中我们可以看到,previewThread线程针对Preview Display,主要完成三个步骤的操作,