Android Camera HAL3 - Multi Camera(1)

本文介紹下 Google Android 在其文檔中對於 Multi-Camera 的描述,以及 Android R 中對 Camera HAL3 的一些新增內容,Multi-Camera 從 Android 9 也就是 P 開始就已經有相關的支持描述了,只不過還是比較簡單的要求,並不是十分的完備。

Android HAL 特指 Google 自己實現的 framework HAL 層級代碼,也就是承接 APP/Framework 和 Vendor HAL 的這部分代碼。下面是 Android 中國區的網址,做的非常好了可以說(文章裏面很多的數據類型都可以從這些網站上面找到):

  1. https://source.android.google.cn/devices/camera
  2. https://developer.android.google.cn/training/camera

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 的時候需要設置,如果不支持的話可以放着不寫,置空即可。
  • 如果單獨請求這部分是支持的話,physicalCameraSettingsphysicalCameraMetadata 就可以對應進行 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 的更加靈活的控制能力。

  1. StreamCombinationSupport
  2. 併發預覽
  3. Camera module HAL 結構體新的接口

對於 CAMERA_MODULE_API_VERSION 來講,2.5 以後在原來的 camera_module_t 結構體裏面新增了 get_physical_camera_infois_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_tcamera3_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 硬件處理子模塊也是會出現的,總是這玩意兒的需求變化太快了,任務每年都很繁重。


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