首页 > 代码库 > Camera框架简介

Camera框架简介

    Camera应用是android多媒体系统中典型的采用C/S架构设计的应用,Client和Server在两个独立的线程间通过Binder机制通信。下面是Camera的总体构架图。

    从应用层的Camera.java(packages\app\Camera),到framework java部分的Camera.java(framework\base\core\java\android\hardware),再到JNI层的android_hardware_camera(framework\base\core),接着转到framework C++部分的Camera.cpp和CameraService.cpp,Camera2Client.cpp。其中Framework C++部分的Binder数据通信结构如下:

                                

下面大致分两个部分来介绍Camera:Camera的初始化以及Camera Preview流程。

Camera的初始化

由于Camera是通过Binder通信的,所以必然会在ServiceManager注册它的service。对应的路径是frameworks\av\media\mediaserver\Main_MediaServer.cpp下有个main函数, 其中CameraService::instantiate()就是注册CameraService服务的。接下来,我们回过头来,从CameraApp的初始化来看这个流程。

点开Camera应用图标后,Camera应用会在Activity的onCreate()方法中启动一个线程叫CameraStartUpThread。在该线程中,按照从启动到预览,分为几个步骤:

1、Open Camera

2、applyXXXCallbacks

3、applyParameters

4、startPreview

注册回调函数主要和Camera预览窗口的图标的点击有关,applyParameter主要和Camera的参数设置相关(如是否开启flash,picture size是多少等等)。这两个后面有机会再展开,这里主要分析openCamera和startPreview。

Util.openCamera(cameraId)

-->CameraHolder.instance().open(cameraId)

-->CameraManager.instance().cameraOpen(cameraId)

-->FrameworksClassFactory.openCamera(cameraId)

-->Camera.open(cameraId)

这里的Camera就是framework java部分的camera了,即framework\base\core\java\android\hardware下的Camera.java。这里的open动作会创建一个Camera实例,实例初始化调用native_setup(newWeakReference<Camera>(this), cameraId, packageName)。从函数名可以看出,调用转到JNI层了,通过JNI的命名规则,我们在android_hardware_Camera.cpp中找到android_hardware_Camera_native_setup()。调用关系:

Camera.open(cameraId)

-->new Camera(cameraId)

-->native_setup(…);

-->sp<Camera> camera = Camera::connect(…)

-->CameraBaseT::connect(…)

-->const sp<ICameraService>& cs =getCameraService();

-->(cs.get()->*fnConnectService)(…)

再注意到Camera.cpp中fnConnectService的赋值CameraTraits<Camera>::TCamConnectServiceCameraTraits<Camera>::fnConnectService = &ICameraService::connect;从上面的图标我们了解到ICameraService也是按照Binder通信的,从其中成员BpCameraService(Client端),BnCameraService(Server端),BpCameraService::connectà BnCameraService:: onTransact,switch语句中走CONNECT分支。注意其中两条语句:

sp<ICameraClient>cameraClient =

interface_cast<ICameraClient>(data.readStrongBinder());

status_tstatus = connect(cameraClient, cameraId,

                    clientName, clientUid,/*out*/ camera);

由Binder知识,connect转到CameraService中的connect,在其中创建了cameraClient为Camera2Client。服务端CameraService在创建时,即在Camera.cpp在从IServiceManager中获取server对象时创建,constsp<ICameraService>& cs = getCameraService();前面提到在CameraService初始化时会创建实例,其中调用到onFirstRef()。hw_get_module函数就是用来获取模块的Hal stub,这里是通过CAMERA_HARDWARE_MODULE_ID 获取Camera Hal层的代理stub,并赋值给mModule,后面就可通过操作mModule完成对Camera模块的控制。以上基本上就完成了对Camera的初始化了。下面再了解一下Camera的预览流程。

 

CameraPreview流程

应用层的Camera一般不设置previewcallback回调,除非你的app设置了 setPreviewCallback,可以看出preview的数据还是可以向上层回调,只是系统默认不回调,另数据采集区与显示区两个缓存区 buffer preview数据的投递,以完成preview实时显示是在HAL层完成的。下面我们还是从应用上层开始逐步跟踪代码流程,详细介绍一下。

 

Camera.java(Camera Application)

-->Camera.java(FrameworokJava)

-->android_hardware_camera.cpp(JNI)

-->Camera.cpp(Client)

-->CameraService.cpp(Server)

-->CameraHarwareInterface(HALinterface)

上层从startPreview开始到JNI层的代码流程大致如下:

startPreview()

1-->mCamera.getCameraDevice().startPreviewAsync()

2-->startPreviewAsync()

3-->mCamera.startPreview()(Framework android_hardware_camera)

4-->android_hardware_Camera_startPreview(…)

 

稍作解释,2)中mCamera.getCameraDevice就是上面介绍的Camera初始化时返回的Util.openCamera(),得到CameraManager.CameraProxy实例,调用startPreviewAsync()实际上就是发了一个消息START_PREVIEW_ASYNC。在收到消息后,3)中调用ICamerastartPreview,这里对应frameworkjava部分的android_hardware_camerastartPreview转到JNI层处理。如同上面分析cameraopen接口一样,大致流程如下:

ICamera::startPreview()

-->ICamera::BpCamerastartPreview()

-->ICamera::BnCameraonTransact()START_PREVIEW case分支

在Camera2Client里将处理preview的请求并进入HAL层

status_t Camera2Client::startPreview() {

     ……

     return startPreviewL(l.mParameters, false);

}

Camera2Client的数据处理和StreamingProcessor相关。

status_t Camera2Client::startPreviewL(Parameters ¶ms,bool restart) {

……

if (!mStreamingProcessor->haveValidPreviewWindow()){

……

}

res =mStreamingProcessor->updatePreviewStream(params);

……

if (!params.recordingHint) {

……

res =mStreamingProcessor->updatePreviewRequest(params);

res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,                outputStreams);

} else {

……

res =mStreamingProcessor->updateRecordingRequest(params);

res =mStreamingProcessor->startStream(StreamingProcessor::RECORD, outputStreams);

}

}

上层应用如果想获取Preview数据,则需要调用setPreviewDisplay(SurfaceHolder),数据将传给上层设置的SurfaceView。在以上函数中红色部分,在mStreamingProcessor->updatePreviewStream(params)中会将上层的SurfaceView转换成IGraphicBufferProducer类型,在Camera2Client中再转换成底层能识别的Surface,并传入StreamingProcessor,以mPreviewWindow指向它。后面的预览数据也就指定传给该Surface了。

最后在updatePreviewRequest(params)中创建一个previewRequest,然后开始向outputStreams中update stream。

 




Camera框架简介