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。

 




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章