Android Camera架構
Android 的相機硬體抽象層 (HAL) 可將 Camera 2 中較高級別的相機框架 API 連線到底層的相機驅動程式和硬體。相機子系統包括相機管道元件的實現,而相機 HAL 則可提供用於實現您的這些元件版本的介面。
一、Camera架構
下面這張圖較好的說明了Camera各元件之間的關係:

圖一.png
應用框架:應用程式碼位於應用框架級別,它使用 Camera 2 API 與相機硬體進行互動。在內部,這些程式碼會呼叫相應的 Binder 介面,以訪問與相機互動的原生程式碼。
AIDL:與 CameraService 關聯的 Binder 介面可在 frameworks/av/camera/aidl/android/hardware 中找到。生成的程式碼會呼叫較低級別的原生程式碼以獲取對實體相機的訪問許可權,並返回用於在框架級別建立 CameraDevice 並最終建立 CameraCaptureSession 物件的資料。
原生框架:此框架位於 frameworks/av/
中,並提供相當於 CameraDevice 和 CameraCaptureSession 類的原生類。另請參閱 NDK camera2 參考 。
Binder IPC 介面:IPC binder 介面用於實現跨越程序邊界的通訊。呼叫相機服務的若干個相機 Binder 類位於 frameworks/av/camera/camera/aidl/android/hardware
目錄中。 ICameraService 是相機服務的介面; ICameraDeviceUser 是已開啟的特定相機裝置的介面; ICameraServiceListener 和 ICameraDeviceCallbacks 分別是對應用框架的 CameraService 和 CameraDevice 回撥。
相機服務:位於 frameworks/av/services/camera/libcameraservice/CameraService.cpp 下的相機服務是與 HAL 進行互動的實際程式碼。
HAL:硬體抽象層定義了由相機服務呼叫、且您必須實現以確保相機硬體正常執行的標準介面。
二、HAL子系統
2.1 capture請求
應用框架會針對捕獲的結果向相機子系統發出請求。一個請求對應一組結果。請求包含有關捕獲和處理這些結果的所有配置資訊。其中包括解析度和畫素格式;手動感測器、鏡頭和閃光燈控制元件;3A 操作模式;RAW 到 YUV 處理控制元件;以及統計資訊的生成等。這樣一來,便可更好地控制結果的輸出和處理。一次可發起多個請求,而且提交請求時不會出現阻塞。請求始終按照接收的順序進行處理。

圖二.png
2.2 HAL 和相機子系統
相機子系統包括相機管道中元件的實現,例如 3A 演算法和處理控制元件。相機 HAL 為您提供了用於實現您的這些元件版本的介面。為了保持多個裝置製造商和影象訊號處理器(ISP,也稱為相機感測器)供應商之間的跨平臺相容性,相機管道模型是虛擬的,且不直接對應於任何真正的 ISP。不過,它與真正的處理管道足夠相似,因此您可以有效地將其對映到硬體。此外,它足夠抽象,可支援多種不同的演算法和運算順序,而不會影響質量、效率或跨裝置相容性。
相機管道還支援應用框架可以啟動來開啟自動對焦等功能的觸發器。它還會將通知傳送迴應用框架,以通知應用自動對焦鎖定或錯誤等事件。

圖三.png
請注意,上圖所示的一些影象處理塊在初始版本中沒有明確定義。相機管道做出以下假設:
- RAW Bayer 輸出在 ISP 內部不經過任何處理。
- 統計資訊根據原始感測器資料生成。
- 將原始感測器資料轉換為 YUV 的各種處理塊按任意順序排列。
- 當顯示多個刻度和剪裁單元時,所有縮放器單元共享輸出區域控制元件(數字縮放)。不過,每個單元都可能具有不同的輸出解析度和畫素格式。
API 用途摘要
下面簡要介紹了使用 Android Camera API 的步驟。有關這些步驟(包括 API 呼叫)的詳細說明,請參閱“啟動和預期操作順序”部分。
- 1.監聽和列舉相機裝置。
- 2.開啟裝置並連線監聽器。
- 3.配置目標使用情形的輸出(如靜態捕獲、錄製等)。
- 4.為目標使用情形建立請求。
- 5.捕獲/重複請求和連拍。
- 6.接收結果元資料和圖片資料。
- 7.切換使用情形時,返回到第 3 步。
HAL 操作摘要
- 捕獲的非同步請求來自於框架。
- HAL 裝置必須按順序處理請求。對於每個請求,均生成輸出結果元資料以及一個或多個輸出影象緩衝區。
- 請求和結果以及後續請求引用的資訊流遵守先進先出規則。
- 指定請求的所有輸出的時間戳必須完全相同,以便框架可以根據需要將它們匹配在一起。
- 所有捕獲配置和狀態(不包括 3A 例程)都包含在請求和結果中。
下面是相機HAL概覽:

圖四.png
2.3 啟動和預期操作順序
本部分詳細說明了使用 Camera API 時應遵循的步驟。有關 HIDL 介面的定義,請參閱 platform/hardware/interfaces/camera/ 。
列舉、開啟相機裝置並建立有效會話
- 1.初始化後,框架開始監聽實現 ICameraProvider 介面的任何現有相機提供程式。如果存在一個或多個此類提供程式,框架將嘗試建立連線。
- 2.框架通過
ICameraProvider::getCameraIdList()
列舉相機裝置。 - 3.框架通過呼叫相應的
ICameraProvider::getCameraDeviceInterface_VX_X()
來例項化一個新的ICameraDevice
。 - 4.框架呼叫
ICameraDevice::open()
來建立一個新的有效捕獲會話 ICameraDeviceSession。
使用有效相機會話
- 1.框架呼叫
ICameraDeviceSession::configureStreams()
並傳入到 HAL 裝置的輸入/輸出流列表。 - 2.框架通過呼叫
ICameraDeviceSession::constructDefaultRequestSettings()
來為某些使用情形請求預設設定。這可能會在ICameraDevice::open
建立ICameraDeviceSession
之後的任何時間發生。 - 3.框架通過基於某一組預設設定的設定以及框架之前註冊的至少一個輸出流來構建第一個捕獲請求並將其傳送到 HAL。此請求通過
ICameraDeviceSession::processCaptureRequest()
傳送到 HAL。HAL 必須阻止此呼叫返回,直到準備好傳送下一個請求為止。 - 4.框架繼續提交請求並根據需要呼叫
ICameraDeviceSession::constructDefaultRequestSettings()
以獲取其他使用情形的預設設定緩衝區。 - 5.當請求捕獲開始(感測器開始曝光以進行捕獲)時,HAL 會呼叫
ICameraDeviceCallback::notify()
並顯示 SHUTTER 訊息,包括幀號和開始曝光的時間戳。此通知回撥不必在對請求第一次呼叫processCaptureResult()
之前發生,但直到針對相應的捕獲呼叫 notify() 之後,才會嚮應用提供有關該捕獲的結果。 - 6.經過一定的管道延遲後,HAL 開始使用
ICameraDeviceCallback::processCaptureResult()
將完成的捕獲返回到框架。這些捕獲按照與提交請求相同的順序返回。一次可發起多個請求,具體取決於相機 HAL 裝置的管道深度。
一段時間後,會出現以下某種情況:
- 框架可能會停止提交新的請求,等待現有捕獲完成(所有緩衝區都已填充,所有結果都已返回),然後再次呼叫
ICameraDeviceSession::configureStreams()
。這會重置相機硬體和管道,以獲得一組新的輸入/輸出流。可重複使用先前配置中的部分資訊流。如果至少還有一個已註冊的輸出流,則框架將從傳送到 HAL 的第一個捕獲請求繼續。(否則,需要先呼叫ICameraDeviceSession::configureStreams()
。) - 框架可能會呼叫
ICameraDeviceSession::close()
以結束相機會話。當框架中沒有其他處於有效狀態的呼叫時,可能隨時會呼叫此函式;不過,在所有發起的捕獲完成(所有結果都已返回,所有緩衝區都已填充)之前,呼叫可能會阻塞。close() 呼叫返回後,不允許再從 HAL 對ICameraDeviceCallback
進行呼叫。一旦進行 close() 呼叫,框架便不能再呼叫其他任何 HAL 裝置函式。 - 在發生錯誤或其他非同步事件時,HAL 必須呼叫
ICameraDeviceCallback::notify()
並返回相應的錯誤/事件訊息。從嚴重的裝置範圍錯誤通知返回後,HAL 的行為方式應像對其呼叫了 close() 一樣。但是,HAL 必須在呼叫 notify() 之前取消或完成所有待處理的捕獲,以便在呼叫 notify() 並返回嚴重錯誤時,框架不會收到來自裝置的更多回調。在 notify() 方法從嚴重錯誤訊息返回後,close() 之外的方法應返回 -ENODEV 或 NULL。
下面是相機操作流程:

圖五.png
2.4 硬體級別
相機裝置可以根據其功能實現多個硬體級別。有關詳情,請參閱 支援的硬體級別 。
2.5 應用捕獲請求、3A 控制元件和處理管道之間的互動
根據 3A 控制元件塊中的設定,相機管道會忽略應用捕獲請求中的某些引數,而改用 3A 控制元件例程提供的值。例如,啟用自動曝光後,感測器的曝光時間、幀時長和感光度引數由平臺 3A 演算法控制,所有應用指定的值都會被忽略。必須在輸出元資料中報告由 3A 例程為幀選擇的值。下表描述了 3A 控制元件塊的不同模式以及由這些模式控制的屬性。有關這些屬性的定義,請參閱 platform/system/media/camera/docs/docs.html 檔案。

image.png
在 圖三 中,影象處理塊中的控制元件都以類似的原理操作,並且每個塊一般都具有 3 種模式:
- OFF:該處理塊處於停用狀態。無法停用去馬賽克、色彩校正和色調曲線調整塊。
- FAST:與 OFF 模式相比,在這種模式下,處理塊可能不會降低輸出幀速率,但是考慮到限制條件,它應該會產生能夠產生的最優質輸出。通常,該模式會用於預覽或視訊錄製模式,或用於連拍靜態影象。在一些裝置上,該模式可能等同於 OFF 模式(進行任何處理都會降低幀速率);而在另外一些裝置上,該模式可能等同於 HIGH_QUALITY 模式(最佳質量仍不會降低幀速率)。
- HIGH_QUALITY:在這種模式下,處理塊應儘可能產生最優質結果,根據需要降低輸出幀速率。通常,該模式會用於拍攝優質靜態影象。一些塊包括可以被選中的手動控制元件(而非 FAST 或 HIGH_QUALITY)。例如,色彩校正塊支援顏色變換矩陣,而色調曲線調整支援任意的全域性色調對映曲線。
相機子系統可以支援的最大幀速率受到多種因素的影響:
- 所請求的輸出影象流的解析度
- 成像器上畫素組合/跳過模式的可用性
- 成像器介面的頻寬
- 各種 ISP 處理塊的頻寬
由於這些因素在不同的 ISP 和感測器之間可能有很大差異,因此相機 HAL 介面會設法將頻寬限制抽象為儘可能簡單的模型。顯示的模型具有以下特性:
- 考慮到應用的請求輸出流大小,影象感測器始終配置為輸出儘可能最小的解析度。最小解析度定義為至少與請求的最大輸出流一樣大。
- 因為任何請求都可能使用當前配置的任意或所有輸出流,所以感測器和 ISP 必須配置為支援將單個捕獲同時擴充套件到所有資訊流。
- 對於不包含 JPEG 流的請求,JPEG 流表現得像經過處理的 YUV 流一樣;在直接引用它們的請求中,它們用作 JPEG 流。
- JPEG 處理器可以並行執行到相機管道的剩餘部分,但不能一次處理多個捕獲。