阅读了很多博客和文档,对android camera系统的架构有了一些了解,借此文总结,备忘。
1.代码总体架构,主要来自http://blog.csdn.net/luozirong/article/details/52244031的总结。
对上图的解释如下:
如上图为Camera的主要框架,其中最上面的Camera.java是应用的使用的接口,它处理维护一个在java层的状态外核心功能都是通过Android_hardware_Camera这个JNI调到C++层实现的。其实他对应的是C++层的一个同名的Camera类。
在C++层的Camera类其实是Binder的client端,对应的Service端是CameraService。每次请求Camera服务时会在CameraService端创建一个CameraClient,并保存在mClient数组里面,同时返回给Client保存在Camera类的mCamera对象里面。这样子CameraService 和Client端的Camera.cpp对象就彻底撒手。对后续的关于Camera操作都是java层调用Camera.cpp,然后直接转交给mCamera,也就是调用CameraClient的方法。CameraService里面的mClient数组的最大长度就是Camera的个数。CameraService在第一次引用的时候会通过HAL标准规范获得一个hw_module_t对象mModule。
CameraClient在创建的时候会获得mModule对象,同时还会创建一个类型为CameraHardwareInterface的mHardware对象,并通过mModule的open函数获得一个HAL设备对象hw_device_tmDevice,这个mDevice与HAL层里面的DefaultCam1Device里面的一个属性对应。CameraDeviceManagerBase顾名思义就是管理Cam1Device的。如此Camera的操作就在CameraClient中交给mHardWare,进一步交给mDevice,再进一步到了Cam1Device。
Java层:
frameworks/base/core/java/android/hardware/Camera.java
Jni层:
frameworks/base/core/jni/android_hardware_Camera.cpp
Client端:
frameworks/av/camera/Camera.cpp
frameworks/av/camera/CameraBase.cpp
frameworks/av/camera/ICameraService.cpp
Service端:
frameworks/av/services/camera/libcameraservice/CameraService.cpp
frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
HAL层:
vendor\mediatek\proprietary\hardware\mtkcam\module_hal\module\module.h
vendor\mediatek\proprietary\hardware\mtkcam\module_hal\devicemgr\CamDeviceManagerBase.cpp
vendor\mediatek\proprietary\hardware\mtkcam\v1\device\Cam1DeviceBase.cpp
2.open camera:主要来自http://blog.csdn.net/w401229755/article/details/52808559的分析
看看由最开始在camera.java中的open函数连接到cameraservice和HAL层的过程:
(这里涉及三套binder通信)
public static Camera open() {
int numberOfCameras = getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
getCameraInfo(i, cameraInfo);
if (cameraInfo.facing ==CameraInfo.CAMERA_FACING_BACK) {
return new Camera(i);
}
}
return null;
}
分两条分析线路,一是getNumberOfCameras()引发的,二是new Camera(i)引发的:
1)getNumberOfCameras()调用流程如下:
--》
JNI:android_hardware_Camera_getNumberOfCameras(JNIEnv*env, jobject thiz)
--》
CameraBase: getNumberOfCameras()
--》
CameraService : getNumberOfCameras()
--》
HAL层:mModule->get_number_of_cameras();。
上面在CameraBase和CameraService直接建立起binder机制,为第一套binder通信机制。
2) new Camera(i)
--》
native_setup(new WeakReference(this),cameraId, packageName)
--》
JNI:
android_hardware_Camera_native_setup(JNIEnv*env, jobject thiz,
jobjectweak_this, jint cameraId, jstring clientPackageName)
--》
Camera.cpp : connect(cameraId,clientName,Camera::USE_CALLING_UID)
--》
cameraservice.cpp : connect(constsp<ICameraClient>& cameraClient, int cameraId,
const String16&clientPackageName, int clientUid, sp<ICamera>& device)
这里在Camera.cpp同样会通过getCameraService();获取CameraService的binder实例,而
cameraservice.cpp会通过newCameraClient()获取client端的binder实例,这样就建立起了双向的binder通信,这样上层对camera的操作才能获得回调响应。
接着继续看看cameraservice中的connect函数往下调的过程:
--》
CameraHardwareInterface.cpp initialize()
--》
Module.h :open_device()
--》
CamDeviceManagerBase :open()
--》
Cam1DeviceFactory.cpp :createCam1Device(String8const s8ClientAppMode, int32_t const i4OpenId)
--》
DefaultCam1Device : onInit()
--》SensorHal和ISP初始化
这里通过Cam1DeviceFactory的createCam1Device创建DefaultCam1Device,它集成自Cam1DeviceBase,而Cam1DeviceBase集成自Cam1Device,
Cam1Device和DefaultCam1Device是每个平台不同的实现,代码在
/vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform中。
而Cam1DeviceBase是android通用代码,在
/vendor/mediatek/proprietary/hardware/mtkcam/legacy/v1/device中。
3.start preview:主要参考自http://blog.csdn.net/shell812/article/details/49425703
--》
Camera.cpp :startPreview()
--》
CameraClient.cpp : startPreview()
--》
CameraClient.cpp : startCameraMode(camera_modemode)
--》
CameraClient::startPreviewMode()
调用到此,开始分为两路,一路是继续调用startPreview,并通过callback将数据返回上层,另外一路将数据塞给surface进行显示。
先来看startPreview这一路:
CameraClient::startPreviewMode()
--》
CameraHardwareInterface.h : startPreview()
--》
DefaultCam1Device:startPreview()
--》
Cam1DeviceBase:startPreview()//重要,做了四件事情,如下四个方法
{
onStartPreview();
enableDisplayClient();
mpCamClient->startPreview();
mpCamAdapter->startPreview();
}
--》
PreviewClient::startPreview()
--》
PreviewClient::initBuffers()
--》
PreviewClient::handleReturnBuffers(Vector<ImgBufQueNode>const&rvQueNode)
--》
PreviewClient::performPreviewCallback(sp<ICameraImgBuf>const&pCameraImgBuf, int32_t const msgType)
然后再通过mDataCb将数据往上回调给应用层。
接下来看显示的过程:
CameraClient::startPreviewMode()
--》
Cam1DeviceBase::setPreviewWindow(preview_stream_ops*window)
--》
DisplayClient::init()
--》
DisplayClient::enableDisplay()
--》
DisplayClient::handleReturnBuffers(Vector<ImgBufQueNode>const& rvQueNode)
--》
DisplayClient:: enquePrvOps(pStreamImgBuf);
enquePrvOps方法里就把数据塞给了由上层设置下来的surface去进行画面的绘制显示。这两条路的主要区别也就是最后的数据流向,一个是通过callback往上传,另一个是通过surface进行绘制。
4.start preview的数据来源
Startpreview做的事情还未分析完,camera数据是从哪里来的还不清楚,看回Cam1DeviceBase:startPreview()方法里,还调用了DefaultCam1Device::onStartPreview()方法,这个方法里调了Cam1DeviceBase::initCameraAdapter()去初始化一个cameraadpter,一般初始MtkDefaultCamAdapter.cpp,CamAdapter是整个Camera的管理者,负责与底层沟通,读取Buf,并负责分配Buf给各个功能操作者,并包括管理着Camer各种属性和算法,如3A,是否自动对焦等。
Cam1DeviceBase:startPreview()做的最后一件事情就是调用CamAdapter->startPreview();
--》
State:StateIdle::onStartPreview(IStateHandler*pHandler)
--》
MtkDefaultCamAdapter ::onHandleStartPreview()这里根据parameters的不同发送不同的命令
--》
Preview相关的命令由PreviewCmdQueThread接收并处理,主要是往驱动层请求数据,对于驱动返回的数据就会被送到上面提到的两个client处理了。
5.take picture:
接下来看看拍照的流程:
Framework层就不看了,从Cam1DeviceBase开始:
Cam1DeviceBase::takePicture()
--》
CamAdapter::takePicture()
--》
StateIdle::onCapture(IStateHandler*pHandler)
--》
CamAdapter::onHandleCapture()
--》
CaptureCmdQueThread::onCapture()
--》
CaptureCmdQueThread::threadLoop()
--》
CamAdapter::onCaptureThreadLoop()
--》
CapBufShot::sendCommand()
à
CapBufShot::onCmd_capture()
--》
SingleShot::startOne(SensorParam const& rSensorParam)
在这里开始往buf里装载image数据,然后就往回调:
CamShotImp::handleDataCallback()
--》
CamShotImp::onDataCallback(CamShotDataInfoconst& msg)
--》
CapBufShot::fgCamShotDataCb()
--》
CapBufShot::handleJpegData()
--》
CamAdapter::onCB_CompressedImage()
然后把数据给到由上层调用takepicture函数时设置的callback里往上传。
以上就是camera的open camera,start preview,take picture三个操作的主要流程。