本文介紹下 Google Android 在其文檔中對於 Multi-Camera 的描述,以及 Android R 中對 Camera HAL3 的一些新增內容,Multi-Camera 從 Android 9 也就是 P 開始就已經有相關的支持描述了,只不過還是比較簡單的要求,並不是十分的完備。
Android HAL 特指 Google 自己實現的 framework HAL 層級代碼,也就是承接 APP/Framework 和 Vendor HAL 的這部分代碼。下面是 Android 中國區的網址,做的非常好了可以說(文章裏面很多的數據類型都可以從這些網站上面找到):
Multi-Camera(來自 Android Develop doc)
Android 9 開始支持一種邏輯多攝像頭設備,需要注意下 Logic camera device 和 Physical camera device 的區別:
- Logical camera device:假設手機上面有三個後攝,那麼一個邏輯攝像頭設備可能包含了其中任意兩個或者三個,至於我本次 request 究竟應該從哪一個或者幾個物理攝像頭設備獲取圖像用於顯示,這是屬於 Vendor HAL implementation 的內容,對於 Android HAL 來講暴露出來的設備就是一個邏輯攝像頭設備,一個邏輯攝像頭設備包含了一個或者多個物理攝像頭設備。
- Physical camera device:假設同上,背面的三個物理攝像頭設備就是 physical camera device,一對一的關係,所以可以認爲 Logical camera device 是 Physical camera device 的超集。
Logical camera device 和 Physical camera device 一樣,對於 Android HAL 來講,它們都是同樣的抽象接口,都會用 CameraDevice/CaptureSession 來進行描述,但是實際 Vendor HAL 那邊內部的邏輯相差還是比較大的。當然 APP 也可以可選地通過 Logical camera device 來控制到 Physical camera device,可以由 stream、meta 以及其它的參數或者接口方法進行控制,某些情況下 Logical stream 和 Physical stream 是可以同時回傳到 Android HAL 的。
Multi-Camera 設備需要通過 logical multi-camera capability 來表明這是一個 Multi-camera 設備,該 metadata 的枚舉類型是 REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
,我們在構建 Vendor HAL 的 CameraCharacteristics 的時候需要將這一項寫入到 REQUEST_AVAILABLE_CAPABLITIES
裏面,在 Android 的 developer 文檔裏面,該項 metadata 的值可能是以下幾種的集合:
BACKWARD_COMPATIBLE
MANUAL_SENSOR
MANUAL_POST_PROCESSING
RAW
PRIVATE_REPROCESSING
READ_SENSOR_SETTINGS
BURST_CAPTURE
YUV_REPROCESSING
DEPTH_OUTPUT
CONSTRAINED_HIGH_SPEED_VIDEO
MOTION_TRACKING
LOGICAL_MULTI_CAMERA
MONOCHROME
SECURE_IMAGE_DATA
SYSTEM_CAMERA
OFFLINE_PROCESSING
Tips: CameraCharacteristics 在 get_camera_info 的時候就被 push 到 Android HAL 那邊了,返回的 camera_info 結構體裏面就包含了這部分信息,而這部分信息一般情況在 Vendor HAL 初始化的時候就構建完成了,需要注意的是在 API29 以及 API28 上面,camera_info 都是針對邏輯攝像頭設備來說的,只不過有的邏輯攝像頭設備是隻包含有一個 physical camera 設備,這部分只包含一個 physical camera 設備的在一定程度上來講也就可以看作是物理攝像頭設備了。
API28 的時候,所有的 physical camera 設備都必須要通過 CameraManager.getCameraIdList()
來 post 出來,但是在 API29 的時候,支持一些並不能獨立 post 出來的 physcial camera 設備不通過這個接口來 post 給 framework,但是這部分設備還是可以使用 CameraManager.getCameraCharacteristics(String)
來進行屬性查詢的。對比與之前的 API29,API30 添加了 onPhysicalCameraAvailable
以及 onPhysicalCameraUnavailable
的回調,這個是在 CameraManager.AvailabilityCallback
裏面的,這部分沒有仔細研究過,需要後續學習。
之前每一個 Logica camera 的 info 裏面包含的 Characteristics 中保存了該 device 下面的 physical camera Id 列表,可以使用 CameraCharacteristics.getPhysicalCameraIds()
來獲取。每一個 Logical camera 下屬的 physical camera device 可能擁有不同的屬性,使用 CameraCharacteristics.getAvailablePhysicalCameraRequestKeys
可以獲取到這部分的信息。Physical camera stream 不支持 reprocess 類型的請求,且只支持 monochrome 以及普通的 Bayer sensor。
Check list
爲了有一個基本的驗證流程,Google 給出了一個檢查列表來表明是否支持 Multi-Camera,這部分就是起一個目錄大綱的作用,具體的細節當然還是有一大堆需要進行驗證實現的。
- 添加
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
枚舉,這個在前面提到過,對於 Vendor HAL 來講就是放在REQUEST_AVAILABLE_CAPABLITIES
裏面的。 - 填充
ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS
,這部分我理解是需要爲每一個 Logical camera 進行填充的,會放在相對應的 camera_info 固定屬性裏面去。 - 填充與深度相關的信息,深度翻譯不太準確,英文就是 Depth-related 信息,包含
ANDROID_LENS_POSE_ROTATION
,ANDROID_LENS_POSE_TRANSLATION
,ANDROID_LENS_INTRINSIC_CALIBRATION
,ANDROID_LENS_DISTORTION
,ANDROID_LENS_POSE_REFERENCE
,這裏面每一個都是與具體的 physical camera device 相關的,所以肯定需要是一個個的數組,裏面的設備順序應該是 Vendor HAL 內部進行順序排定的。 - 設置 StaticCharacteristics 的
ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
參數,取值有兩個:ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE
:表示是 Master-Master 模式的 sensor 同步方式,字義理解就是全部靠軟件來進行實現,硬件級別沒有什麼硬件電路來做相關的同步措施。ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED
:表示 Master-Slave 模式的同步方式,既有軟件也有硬件級別的同步,硬件需要進行 shutter 和曝光時間的雙重同步,這部分是有專門的硬件電路的。
- 設置
ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS
這一個參數只在支持對一個 Logical camera device 下屬的 Physical camera device 單獨請求 request 的時候需要設置,如果不支持的話可以放着不寫,置空即可。 - 如果單獨請求這部分是支持的話,
physicalCameraSettings
與physicalCameraMetadata
就可以對應進行 request 和 result 的屬性設置和返回結果。這部分在下一小節說明,HAL3.5 加了一些接口來完成這部分功能。 - 對於 HAL3.5 (也就是 Android 10) 開始,需要在返回的 result 裏面設置
ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID
參數,這個是表明當前 request 對應的 Logical camera 下屬有哪些 Physical camera 是處於 active 狀態的。
性能和耗電:對於一些配置了 Physical stream 的 request 來講,可能會拖慢 Logical stream 的處理速度,導致整體幀率的降低,同時也將會導致更多的耗電量。一句話就是並不保證完全流暢的處理請求,一般情況下是指不保證所有平臺所有 Physical stream 配置方式都能夠實現非常流暢的 request 處理效果,不過我想對於大部分旗艦產品來講這部分流暢處理應該是必要的,不然競爭力就可能會下降。
HAL 3.5
簡單的來說 HAL3.5 增加了對 Physical camera 更全面的支持,也就是增加了多 Physical camera 操作的部分,其中最明顯的就是併發預覽,比如同時打開三個攝像頭並且輸出三路數據給到 APP 同時顯示在 UI 上面,也支持同時多路錄像,總之 HAL3.5 最明顯的就是開放對於 Physical camera 的更加靈活的控制能力。
- StreamCombinationSupport
- 併發預覽
- Camera module HAL 結構體新的接口
對於 CAMERA_MODULE_API_VERSION 來講,2.5 以後在原來的 camera_module_t
結構體裏面新增了 get_physical_camera_info
和 is_stream_combination_supported
兩個函數。前者是用於獲取非獨立 Physical camera device 的 Characteristics 信息的,但是傳入的 camera id 是比較特別的,他並不是屬於 get_number_of_cameras
函數返回值範圍內的,而是大於那個返回值得一個數,相關的 Physical camera 信息在 ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS
裏面存放,是相對於 Logical camera 來講的。後者是用於判斷組合起來的 stream 是否支持,這些 stream 包含輸入的和輸出的 stream,以往使用的時候一般都是協商好的 stream 組合然後進行配置,這個項相當於是增加了一個靈活配置項,我可以運行時判斷是否支持,比如說我現在這一個 request 中包含了一個 input stream,還有分別對應三個 Physical camera 的 output stream,那麼很多平臺可能就是無法支持的,這個時候就可以通過該函數來進行判定,避免配置一個不支持的 stream 進去。這兩個接口也可以在 /platform/hardware/interfaces/camera/device/3.5/ICameraDevice.hal
這裏找到定義。
併發預覽前面稍微介紹過,最主要的體現可以在原來的 camera3_capture_result_t
和 camera3_capture_request_t
,HAL3.5 新增或者改變了一下幾個成員變量:
typedef struct camera3_stream {
/**
* The physical camera id this stream belongs to.
*
* <= CAMERA_DEVICE_API_VERISON_3_4:
*
* Not defined and must not be accessed.
*
* >= CAMERA_DEVICE_API_VERISON_3_5:
*
* Always set by camera service. If the camera device is not a logical
* multi camera, or if the camera is a logical multi camera but the stream
* is not a physical output stream, this field will point to a 0-length
* string.
*
* A logical multi camera is a camera device backed by multiple physical
* cameras that are also exposed to the application. And for a logical
* multi camera, a physical output stream is an output stream specifically
* requested on an underlying physical camera.
*
* For an input stream, this field is guaranteed to be a 0-length string.
*/
const char* physical_camera_id;
} camera3_stream_t;
typedef struct camera3_capture_request {
uint32_t num_physcam_settings;
const char **physcam_id;
const camera_metadata_t **physcam_settings;
} camera3_capture_request_t;
在 configure_stream 的時候,新增了 Android HAL 層必須設置的成員變量 physical_camera_id
,用於標識該 camera stream 是屬於哪一個 Physical stream 的,如果是 Logical stream 的話就會設置爲 0 長度的字符串。該成員變量配合 camera3_capture_request
結構體裏面個 output buffer 以及 physical settings 來對每一個 physical camera 進行區分,達到併發預覽的目的。
End
本文對 Multi camera 所支持的主要特性和細節點做了一個簡單的描述,實現起來當然還是有非常多的細節去深究的,這裏也分了系列來進行介紹,下一篇應該會是 CameraX 的部分介紹,這個是在 Android 11 上面新發布的一個特性,釋放了更多的標準化功能給到三方 camera app 去使用。隨着 5G 時代的到來,短視頻越來越多的被使用,與之對應的拍攝能力也是在不斷變換着需求,尤其是對於視頻防抖的要求比較急需,以後還會有更多越來越標準化的算法也下放到 camera 硬件裏面去做,從底層來爲視頻拍攝提供更方便的處理方式,camera 智能化也是一個趨勢,引入硬件化的 camera AI 硬件處理子模塊也是會出現的,總是這玩意兒的需求變化太快了,任務每年都很繁重。