首页 > 代码库 > 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)中调用ICamera的startPreview,这里对应frameworkjava部分的android_hardware_camera的startPreview转到JNI层处理。如同上面分析camera的open接口一样,大致流程如下:
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框架简介