寫(xiě)在開(kāi)頭:本文為學(xué)習(xí) camera2 過(guò)程中的知識(shí)點(diǎn)歸納總結(jié)谎替。
1. camera2 相機(jī)體系結(jié)構(gòu)
https://blog.csdn.net/u012596975/article/details/107138177
對(duì)于Camera Api v2的實(shí)現(xiàn),是通過(guò)Camera Framework來(lái)完成的藤为,而該層也有著一次不小的演變,剛開(kāi)始Framework層并不是直接通過(guò)AIDL接口與Camera Service進(jìn)行通信藏雏,而是通過(guò)一個(gè)JNI層來(lái)完成從Java到Native的轉(zhuǎn)換鹤啡,而Native部分作為客戶(hù)端,保持對(duì)Service的通信清蚀。這種設(shè)計(jì)匕荸,很顯然會(huì)比較臃腫,并且代碼難以維護(hù)枷邪,所以之后由于AIDL接口的提出榛搔,谷歌直接將其加入到相機(jī)框架中,用于保持Framework與Service的通信东揣,進(jìn)而擯棄了JNI層践惑,進(jìn)一步減少了不必要的層級(jí)結(jié)構(gòu),保持了整個(gè)體系簡(jiǎn)潔性嘶卧。
更多可參考 深入理解Android相機(jī)體系結(jié)構(gòu) 系列尔觉。
2. camera1和camera2的使用簡(jiǎn)單對(duì)比
先回顧一下,camera1和camera2的簡(jiǎn)單使用脸候。
這兩篇camera1和camera2的預(yù)覽demo穷娱,十分簡(jiǎn)潔,功能單一运沦,可供對(duì)比泵额。
Android Camera1最簡(jiǎn)單的預(yù)覽框顯示
Android Camera2最簡(jiǎn)單的預(yù)覽框顯示
下面這兩張思維導(dǎo)圖,較為詳細(xì)得說(shuō)明了camera的使用流程和API携添。這不是本篇的重點(diǎn)嫁盲。
camera1 的 open 簡(jiǎn)單代碼流程可參考這篇:
Android Camera open 從上到下代碼流程
camera2 的 open 簡(jiǎn)單代碼流程可參考這篇:
Android CameraManager open 從上到下代碼流程
如果需要更詳細(xì)的demo,可參考官方的 demo:cameraview
camera1和camera2 的調(diào)用流程對(duì)比烈掠,可參考這張圖羞秤。可以看到,API V2是沒(méi)有通過(guò)JNI的api的左敌,這里是直接調(diào)用的service瘾蛋。
谷歌在Andorid 5.0(API Level 21)便重新對(duì)Camera進(jìn)行了設(shè)計(jì),摒棄了Camera Api v1的設(shè)計(jì)邏輯矫限,提出了一個(gè)全新的API – camera2哺哼,引入了Session以及Request概念,將控制邏輯統(tǒng)一成一個(gè)視圖叼风,因此在使用上更加復(fù)雜取董,同時(shí)也支持了更多特性,比如逐幀控制曝光无宿、感光度以及支持Raw格式的輸出等茵汰。并且由于對(duì)控制邏輯的高度抽象化,使得該接口具有很高的靈活性孽鸡,可以通過(guò)簡(jiǎn)單的操作實(shí)現(xiàn)30fps的全高清連拍的功能蹂午,總得來(lái)說(shuō),該接口極大地提高了對(duì)于相機(jī)框架的控制能力彬碱,同時(shí)也進(jìn)一步大幅度提升了其整體性能画侣。
camera2的應(yīng)用層與framework層之間的流程如下:
簡(jiǎn)單來(lái)說(shuō)就是,引入了Session以及Request堡妒,使用更加復(fù)雜配乱,功能多,更加靈活了皮迟。
注意搬泥,雖然新增了camera2的api,camera1的代碼依然在android源碼中伏尼。分析的時(shí)候要注意忿檩。
frameworks/base/core/java/android/hardware/camera2/
這個(gè)目錄下的是camera2的framework層代碼。
Camera整體架構(gòu)簡(jiǎn)述
忽略掉驅(qū)動(dòng)層爆阶,就是這張圖燥透。
了解完Android Camera工作大體流程后沙咏,來(lái)看看部分細(xì)節(jié)。
2. 源碼簡(jiǎn)單分析
本篇源碼分析班套,不會(huì)涉及驅(qū)動(dòng)層及以下(最多一點(diǎn)點(diǎn))肢藐。另由于MTK和高通camera,還有android原生的吱韭,在camera這塊差異很大吆豹,流程分析查找資料的時(shí)候要注意下。
Android Camera工作大體流程:
出處: https://blog.csdn.net/TaylorPotter/article/details/105387109
綠色框中是應(yīng)用開(kāi)發(fā)者需要做的操作,藍(lán)色為AOSP提供的API,黃色為Native Framework Service,紫色為HAL層Service.
描述一下步驟:
- 1.App一般在MainActivity中使用SurfaceView或者SurfaceTexture + TextureView或者GLSurfaceView等控件作為顯示預(yù)覽界面的控件,共同點(diǎn)都是包含了一個(gè)單獨(dú)的Surface作為取相機(jī)數(shù)據(jù)的容器.
- 2.在MainActivity onCreate的時(shí)候調(diào)用API 去通知Framework Native Service CameraServer去connect HAL繼而打開(kāi)Camera硬件sensor.
- 3.openCamera成功會(huì)有回調(diào)從CameraServer通知到App,在onOpenedCamera或類(lèi)似回調(diào)中去調(diào)用類(lèi)似startPreview的操作.此時(shí)會(huì)創(chuàng)建CameraCaptureSession,創(chuàng)建過(guò)程中會(huì)向CameraServer調(diào)用ConfigureStream的操作,ConfigureStream的參數(shù)中包含了第一步中空間中的Surface的引用,相當(dāng)于App將Surface容器給到了CameraServer,CameraServer包裝了下該Surface容器為stream,通過(guò)HIDL傳遞給HAL,繼而HAL也做configureStream操作
- 4.ConfigureStream成功后CameraServer會(huì)給App回調(diào)通知ConfigStream成功,接下來(lái)App便會(huì)調(diào)用AOSP setRepeatingRequest接口給到CameraServer,CameraServer初始化時(shí)便起來(lái)了一個(gè)死循環(huán)線(xiàn)程等待來(lái)接收Request.
- 5.CameraServer將request交到Hal層去處理,得到HAL處理結(jié)果后取出該Request的處理Result中的Buffer填到App給到的容器中,
SetRepeatingRequest 為了預(yù)覽,則交給Preview的Surface容器,如果是Capture Request則將收到的Buffer交給ImageReader的Surface容器. - 6.Surface本質(zhì)上是BufferQueue的使用者和封裝者,當(dāng)CameraServer中App設(shè)置來(lái)的Surface容器被填滿(mǎn)了BufferQueue機(jī)制將會(huì)通知到應(yīng)用,此時(shí)App中控件取出各自容器中的內(nèi)容消費(fèi)掉,Preview控件中的Surface中的內(nèi)容將通過(guò)View提供到SurfaceFlinger中進(jìn)行合成最終顯示出來(lái),即預(yù)覽;而ImageReader中的Surface被填了,則App將會(huì)取出保存成圖片文件消費(fèi)掉.
簡(jiǎn)單圖如下:
https://blog.csdn.net/TaylorPotter/article/details/105387109
通過(guò)AIDL binder調(diào)用向Framework層的CameraServer進(jìn)程下指令,從CameraServer進(jìn)程中取的數(shù)據(jù).
基本過(guò)程都如下:
- 1.openCamera:Sensor上電
- 2.configureStream: 該步就是將控件如GLSurfaceView,ImageReader等中的Surface容器給到CameraServer.
- 3.request: 預(yù)覽使用SetRepeatingRequest,拍一張可以使用Capture,本質(zhì)都是setRequest給到CameraServer
- 4.CameraServer將Request的處理結(jié)果Buffer數(shù)據(jù)填到對(duì)應(yīng)的Surface容器中,填完后由BufferQueue機(jī)制回調(diào)到引用層對(duì)應(yīng)的Surface控件的CallBack處理函數(shù),接下來(lái)要顯示預(yù)覽或保圖片App中對(duì)應(yīng)的Surface中都有數(shù)據(jù)了
著重看看以下幾點(diǎn)
- CameraService和CameraProvider服務(wù)啟動(dòng)
- open
- configure
- request
2.1 CameraService和CameraProvider服務(wù)啟動(dòng)
層級(jí)架構(gòu)概覽
總體邏輯順序計(jì)
(1) CameraProvider進(jìn)程啟動(dòng)理盆、注冊(cè)
(2) CameraServer進(jìn)程啟動(dòng)痘煤、注冊(cè)、初始化
(3) CameraServer初始化過(guò)程中通過(guò)HIDL通信獲取CameraProvider猿规,并對(duì) CameraProvider進(jìn)行初始化
CameraService和CameraProvider初始化
CameraServer初始化
具體代碼流程可參考:
Android 8.1 Camera2架構(gòu)解析(1) CameraService和CameraProvider服務(wù)啟動(dòng)流程
[Android O] Camera 服務(wù)啟動(dòng)流程簡(jiǎn)析
2.2 open
可直接參考這篇:
camera framework open流程
有道筆記上排版更好衷快。
camera2 open流程
最后來(lái)張時(shí)序圖加深下印象。
2.3 configure
以下代碼出自這篇Android Camera2最簡(jiǎn)單的預(yù)覽框顯示姨俩。
/**
* 打開(kāi)相機(jī)烦磁,預(yù)覽是在回調(diào)里面執(zhí)行的。
*/
private void openCamera() {
try {
// 4.權(quán)限檢查
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
requestCameraPermission();
return;
}
// 5.真正打開(kāi)相機(jī)
Log.i(TAG, "openCamera");
mCameraManager.openCamera(mCameraId, mStateCallback, null);
} catch (CameraAccessException e) {
Log.e(TAG, "openCamera error = " + e.getMessage());
}
/**
* 相機(jī)狀態(tài)監(jiān)聽(tīng)對(duì)象
*/
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
Log.i(TAG, "StateCallback哼勇! onOpened");
mCameraDevice = camera; // 打開(kāi)成功都伪,保存代表相機(jī)的CameraDevice實(shí)例
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mTextureView.getWidth(), mTextureView.getHeight());
Surface surface = new Surface(surfaceTexture);
ArrayList<Surface> previewList = new ArrayList<>();
previewList.add(surface);
try {
// 6.將TextureView的surface傳遞給CameraDevice
mCameraDevice.createCaptureSession(previewList, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
try {
CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(surface); // 必須設(shè)置才能正常預(yù)覽
CaptureRequest captureRequest = builder.build();
// 7.CameraCaptureSession與CaptureRequest綁定(這是最后一步,已可顯示相機(jī)預(yù)覽)
session.setRepeatingRequest(captureRequest, mSessionCaptureCallback, null);
} catch (CameraAccessException e) {
Log.e(TAG, "createCaptureRequest error = " + e.getMessage());
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Log.e(TAG, "onConfigureFailed");
}
}, null);
} catch (CameraAccessException e) {
Log.e(TAG, "createCaptureSession error = " + e.getMessage());
}
}
應(yīng)用層在openCamera之后积担,會(huì)調(diào)用createCaptureSession陨晶。
createCaptureSession之后的流程可參考這篇:
camera framework configure流程分析
涉及到的主要類(lèi):
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java#632
出處:https://blog.csdn.net/haodada1226/article/details/121719939
總結(jié)一下:
① configure為app傳入的surface配置相應(yīng)的stream,然后將gbp帝璧、streamid先誉、surfaceid進(jìn)行綁定,以便于發(fā)送request請(qǐng)求的時(shí)候去獲鹊乃浮褐耳;
② 告訴hal層,需要從camera中獲取什么樣格式的buffer
簡(jiǎn)單版時(shí)序圖
復(fù)雜版時(shí)序圖
2.4 request
在 Android Camera2最簡(jiǎn)單的預(yù)覽框顯示 這篇文的代碼中可以看到渴庆,
調(diào)用createCaptureRequest之后通過(guò)build創(chuàng)建CaptureRequest铃芦,然后session.setRepeatingRequest
,然后就可以預(yù)覽了襟雷。
然后接下來(lái)的流程可直接參考這篇:
camera framework request流程
涉及到的主要類(lèi)如下:
http://aosp.opersys.com/xref/android-9.0.0_r61/xref/frameworks/base/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java#121
出處: https://blog.csdn.net/haodada1226/article/details/121848769
這里總結(jié)一下:
configure的時(shí)候?yàn)槊總€(gè)surface創(chuàng)建相應(yīng)的Camera3OutputStream刃滓,然后將相應(yīng)的信息保存起來(lái)(注意CameraDeviceClient中的mStreamMap、mConfiguredOutputs以及Camera3Device中的mOutputStreams等)耸弄,然后告訴hal層需要配置什么格式咧虎、分辨率等的流。request中會(huì)將上述的surfaces和outputStreams填充進(jìn)request請(qǐng)求中计呈,然后在Camera3Device中起一個(gè)thread砰诵,一直向hal層發(fā)送request請(qǐng)求征唬。
最后來(lái)張時(shí)序圖
3.camera中的BufferQueue
http://www.reibang.com/p/05a8d6f5b4df
BufferQueue可以理解為一個(gè)生產(chǎn)者-消費(fèi)者”模型,對(duì)GraphicBuffer管理的一種機(jī)制茁彭。
需注意的是总寒,可以將BufferQueue當(dāng)作是一個(gè)算法結(jié)構(gòu),并不是只有Surfaceflinger會(huì)使用到尉间,其他進(jìn)程只要有GraphicBuffer的消費(fèi)地方都會(huì)使用到偿乖。
BufferQueue結(jié)構(gòu)
http://www.reibang.com/p/05a8d6f5b4df
圖形生產(chǎn)者(如相機(jī)击罪,View繪制等)先向BufferQueue申請(qǐng)GraphicBuffer哲嘲,填充完GraphicBuffer后,將GraphicBuffer移交給BufferQueue媳禁,BufferQueue會(huì)通知圖形消費(fèi)者(如Surfaceflinger眠副,ImageReader,GLConsumer等)
相機(jī)中preview使用到的TextureView中的成員SurfaceTexture就是個(gè)自帶BufferQueue的組件竣稽。
http://www.reibang.com/p/05a8d6f5b4df
框架流程匯總
參考鏈接:
深入理解Android相機(jī)體系結(jié)構(gòu)之二
深入理解Android相機(jī)體系結(jié)構(gòu)之三
深入理解Android相機(jī)體系結(jié)構(gòu)之十
Android Camera簡(jiǎn)單整理(一)-Camera Android架構(gòu)(基于Q)
Android Camera簡(jiǎn)單整理(三)-Mtk Camera MtkCam3架構(gòu)學(xué)習(xí)
[Android O] Camera 服務(wù)啟動(dòng)流程簡(jiǎn)析
CameraService啟動(dòng)流程
Android 8.1 Camera2架構(gòu)解析(1) CameraService和CameraProvider服務(wù)啟動(dòng)流程
Camera service服務(wù)啟動(dòng)流程
BufferQueue詳解 原理
Android-Fk:BufferQueue學(xué)習(xí)整理
Android Camera2 Framwork+Hal+Surface整體數(shù)據(jù)流程
Android Camera 打開(kāi)預(yù)覽流程分析(三)-- Camera 連接到CameraService 過(guò)程分析
camera framework configure流程分析
Camera2 API -- OutputConfiguration
camera framework configure流程分析