如第一章所述,得到CameraDevice對象後就可以創建session了,還是以createCaptureSession爲例,這是一個抽象方法,我們已經介紹過,它的實現在CameraDeviceImpl中。
方法首先將傳入的Surface構建OutputConfiguration,OutputConfiguration是輸出的Surface的配置,包含一些基本的配置信息。
隨後調用createCaptureSessionInternal方法,如同Camera open時最終都是調用openCameraDeviceUserAsync方法一樣,create session最終也都是調用這個方法。
首先判斷異常情況,包括相機已經關閉、相機出錯以及high speed限制。判斷session是否爲空,如果不爲空就調用CameraCaptureSessionCore的
replaceSessionClose方法。
CameraCaptureSessionCore是一個接口,它的實現是CameraCaptureSessionImpl。
- replaceSessionClose方法調用了 close方法;
- 調用CameraDeviceImpl的stopRepeating方法;
- 調用ICameraDeviceUser的cancelRequest();
- 在Camera open的地方我們已經知道,在AIDL的另一頭的實現是CameraDeviceClient,所以調用它的cancelRequest();
- 調用Camera3Device的clearStreamingRequest()方法,最終調用clear方法;clear方法會清空RepeatingRequests list,然後遍歷並清空隊列中的buffer。
完成這些操作,當前正在運行的session就close了。
接下來調用configureStreamsChecked方法,這個方法的作用是create stream。
首先檢查outputConfiguration和inputConfiguration,確保配置正確。
接着檢查Camera的狀態,如果有異常則關閉camera,拋出異常。
遍歷outputConfigurations,確定哪些config需要創建steam和需要刪除。
mCallOnBusy內部有一個同步鎖mInterfaceLock,configureStreamsChecked方法也有這個鎖,所以它會等configureStreamsChecked方法執行完才執行run方法。StateCallbackKK是CameraDeviceImpl的一個內部靜態抽象類,包含了session的一些狀態,與CameraCaptureSession.StateCallback是不同的。
接下來調用waitUntilIdle方法,我們可以直接到CameraDeviceClient中找到相應的方法,在經過了多個狀態判斷之後,調用的核心代碼是mDevice的waitUntilDrained方法,我們已經知道mDevice是Camera3Device,直接去查看。跳過中間步驟,最終的核心代碼是一個do…while循環。如果status是active就結束。
Create steam
接下來就正式開始創建steam。
由於inputConfiguration通常是null所以直接看createSteam方法。
方法首先進行了大量狀態判斷,
然後遍歷bufferProducers,這部分是android的surface機制相關的內容,我們也暫時不管。
接下來這段就是核心方法,調用Camera3Device的createSteam方法。
同樣做了多個判斷。在switch中判斷mStatus的狀態,在初次創建Camera3Device的時候,initialize方法調用initializeCommonLocked方法,調用internalUpdateStatusLocked方法時,mStatus賦值爲STATUS_UNCONFIGURED,
所以在上面的代碼中直接執行了break語句,跳出來switch。
在判斷都沒有異常的情況下,就進入流的創建。根據流的類型不同,調用不同的構造方法。
創建完steam之後,就steam設置id,
Id是在已有的基礎上+1,所以如果有多個流,id就是連續的數字,至此一個steam就創建完成了。回到CameraDeviceImpl中,for循環遍歷outconfig,也就是遍歷surfaces,創建多個steam。
方法的最後調用endConfigure方法,我們依然到CameraDeviceClient中查看endConfigure方法的源碼,可以看到核心的代碼是調用Camera3Device中的configureStreams方法,直接查看源碼。
-> filterParamsAndConfigureLocked方法-> configureStreamsLocked方法
這個方法的主要行爲是給已經創建的steam添加buffersize、執行HAL配置、結束配置。
配置成功就調用outputStream的finishConfiguration方法。這個方法在Camera3Stream中實現,並調用子類Camera3OutputStream的configureQueueLocked的方法。在這個方法裏最重要的是
這句話。
前面提到mConsumer就是surface,執行surface的connect方法。
這裏是我們第二次遇到Surface機制的內容。
當遇到Camera的preview黑屏無法顯示的問題,如果出現了與Surface相關的異常,那麼就是可能是這兩個地方存在問題。一是GraphicBufferProducer構建出現問題,傳入的gbp是null,二是當前surface的GraphicBufferProducer有其他鏈接。
之後就是根據connect返回的狀態進行處理,計算mTotalBufferCount等操作。
至此steam的創建就全部完成了。
Create Session
Steam創建成功只有,就做好了創建session的全部準備工作了。
創建CameraCaptureSessionImpl對象,它是CameraCaptureSession的子類。
這個構造方法裏,除去直接構建的全局變量,主要就是構建StateCallback的createUserStateCallbackProxy方法,方法創建了一個SessionStateCallbackProxy對象,這個類是CameraCaptureSession.StateCallback的子類,並且內部持有一個StateCallback的對象,也就是APP創建並傳下來的callback。
CameraCaptureSessionImpl的構造函數的最後,如果一切配置正常就調用StateCallback的onConfiged方法,APP就會在會調用執行應用定義的行爲,一般就是構建CaptureRequest。
至此Session就全部創建完成了。
總結
通過上面代碼的分析,我們可以看到創建session主要有三個步驟
- 創建outputConfiguration;
- 創建Steam;
- 創建Session,調用Callback;