相機 HAL3 緩衝區管理 API

Android 10 推出了選用功能 相機 HAL3 緩衝區 管理 API 實作緩衝區管理邏輯,實現不同的記憶體 相機 HAL 實作的延遲時間取捨。

相機 HAL 需有 N 個要求 (其中 N 等於 管道深度) 會排入其管道的佇列中,但通常不需要全部的 N 集合 會同時輸出緩衝區。

例如 HAL 可能有八個要求在管道中排入佇列 只需針對最後一個階段的最後兩個要求 這種模型通常已開放原始碼 可以透過自訂筆記本或管線微調在搭載 Android 9 以下版本的裝置上,相機架構會配置 緩衝區,因此可能會有六組 中未使用的緩衝區。在 Android 10 中, 相機 HAL3 緩衝區管理 API 可將輸出內容分離 才能釋放六組緩衝區。這會導致 在高階裝置上節省多達 MB 的記憶體容量 且記憶體容量不足的裝置

圖 1 顯示執行中裝置的相機 HAL 介面圖 Android 9 以下版本。圖 2 顯示 Android 中的相機 HAL 介面 10 搭配 相機 HAL3 緩衝區管理 API

9 以下版本的緩衝區管理

圖 1. Android 9 以下版本的相機 HAL 介面

Android 10 中的緩衝區管理

圖 2. Android 10 中使用緩衝區管理 API 的相機 HAL 介面

實作緩衝區管理 API

如要實作緩衝區管理 API,相機 HAL 必須:

相機 HAL 會使用 requestStreamBuffers敬上 和 returnStreamBuffers。 用於 ICameraDeviceCallback.hal 要求並傳回緩衝區。HAL 也必須導入 signalStreamFlush敬上 方法 ICameraDeviceSession.hal。 指示相機 HAL 傳回緩衝區。

requestStreamBuffers

使用 requestStreamBuffers敬上 方法來要求相機架構中的緩衝區。使用相機 HAL3 時 緩衝區管理 API,從相機架構擷取要求就不會 包含輸出緩衝區,也就是 bufferId 欄位 StreamBuffer0。因此,相機 HAL 必須使用 requestStreamBuffers 提出要求 才能擷取到相機架構中的緩衝區

requestStreamBuffers 方法可讓呼叫端要求多個緩衝區 以便減少 HIDL IPC 呼叫。然而,若是呼叫出更多緩衝區,則呼叫會花費較多時間 這樣可能會對產生結果的總延遲時間造成負面影響 此外,因為對 requestStreamBuffers 的呼叫在相機中序列化 服務,建議相機 HAL 使用專屬的高優先順序 執行緒要求,以要求緩衝區。

如果緩衝區要求失敗,相機 HAL 必須能正確處理 一般錯誤。下方清單說明緩衝的常見原因 要求及應如何由相機 HAL 處理。

  • 應用程式與輸出串流中斷連線: 這是一般錯誤。相機 HAL 應該 ERROR_REQUEST敬上 任何擷取要求 指定已取消連結的串流並準備好處理後續要求 一般問題。
  • 逾時:應用程式忙碌時,就可能發生這種情況 會密集處理,但會保留一些緩衝區。相機 HAL 應該 傳送 ERROR_REQUEST敬上 很方便擷取 逾時錯誤並準備好正常處理後續要求。
  • 相機架構正在準備新的串流設定: 相機 HAL 應會等待下一次 configureStreams敬上 呼叫完成,才能再次呼叫 requestStreamBuffers
  • 相機 HAL 達到了 緩衝區限制 (maxBuffers 欄位): 相機 HAL 應會等待 直到其在呼叫之前傳回至少一個串流緩衝區 requestStreamBuffers

returnStreamBuffers

使用 returnStreamBuffers敬上 方法,將額外的緩衝區傳回相機架構。相機 HAL 正常 會透過 processCaptureResult敬上 方法,但只會處理已傳送至 相機 HAL使用 requestStreamBuffers 方法時, 相機 HAL 實作能保留更多緩衝區,超過 相機架構因此,returnStreamBuffers 方法應 如果 HAL 實作所保留的緩衝區不超過所要求的數量, 相機 HAL 實作不需要呼叫 returnStreamBuffers 方法。

訊號串流 Flush

signalStreamFlush敬上 方法是由相機架構呼叫 方法,藉此通知相機 HAL 傳回所有 大量緩衝區當相機架構即將接近時,通常就會呼叫此方法 通話 configureStreams敬上 因此必須清空相機拍攝管道和「returnStreamBuffers」類似 方法,如果相機 HAL 實作所保留的緩衝區超過 此方法可以有空白的實作。

相機架構呼叫後 signalStreamFlush、 架構會停止向相機 HAL 傳送新的擷取要求 緩衝區傳回相機架構當所有緩衝區皆處於 傳回,requestStreamBuffers 方法呼叫失敗,且相機 讓架構繼續保持乾淨接著,相機架構 會呼叫 configureStreams敬上 或 processCaptureRequest。 方法。如果相機架構呼叫 configureStreams 方法,相機 HAL 可以在 configureStreams 呼叫傳回後,再次開始要求緩衝區 如果相機架構呼叫 processCaptureRequest 方法, 相機 HAL 可以在 processCaptureRequest 期間開始要求緩衝區 呼叫。

signalStreamFlush 方法和 flush 方法。呼叫 flush 方法後,HAL 可以取消待處理擷取 要求 ERROR_REQUEST 以盡快清空管道時間 系統會呼叫 signalStreamFlush 方法,HAL 必須完成所有待處理 正常擷取要求,然後將所有緩衝區傳回相機架構。

signalStreamFlush 方法和其他方法的另一個差異為 指定 signalStreamFlush單向的 HIDL 方法,也就是說,相機 架構可能會在 HAL 收到 signalStreamFlush 呼叫。也就是說 signalStreamFlush 方法和其他方法 (特別是 configureStreams 方法) 抵達相機 HAL 的順序可能不同 比起相機架構中的呼叫順序解決方式 非同步問題,streamConfigCounter 欄位已新增至 StreamConfiguration 並新增為 signalStreamFlush 的引數 方法。相機 HAL 實作應使用 streamConfigCounter 引數,判斷 signalStreamFlush 呼叫是否晚於其它的抵達時間 對應的 configureStreams 呼叫。請參閱圖 3 範例。

處理遲到的呼叫

圖 3. 相機 HAL 應如何偵測及處理延遲抵達的 SignalStreamFlush 通話

實作緩衝區管理 API 時的行為變更

使用緩衝區管理 API 實作緩衝區管理邏輯時, 請考慮以下潛在的相機行為變化 和相機 HAL 實作:

  • 更快收到相機 HAL 發出的要求 :如果沒有緩衝區管理 API,相機架構就會要求 每個擷取要求都會輸出緩衝區,再傳送擷取要求給 相機 HAL使用緩衝區管理 API 時,相機架構 不必等待緩衝區,進而傳送擷取要求 相機 HAL

    此外,如果沒有緩衝區管理 API,相機架構就會停止運作 如果擷取的輸出串流的其中一個輸出串流,則傳送擷取要求 要求已達到 HAL 可以保留的緩衝區數量上限 一次 (這個值是由相機 HAL 指定 configureStreams 傳回值中的 HalStream::maxBuffers 欄位 呼叫)。透過緩衝區管理 API,這項調節行為就不再出現 且相機 HAL 實作不得接受 當 HAL 有太多擷取要求時,processCaptureRequest 呼叫 已排入佇列。

  • requestStreamBuffers 呼叫的延遲時間差異很大: 導致 requestStreamBuffers 呼叫花費的時間 例如:

    • 針對新建串流的前幾個緩衝區,呼叫 也可能需要更長的時間,因為裝置需要分配記憶體。
    • 預估延遲時間會隨 緩衝區。
    • 應用程式保留緩衝區,且正在處理中。這個 可能會導致緩衝區要求速度變慢或命中逾時, 就沒有緩衝區或 CPU 速度緩慢

緩衝區管理策略

緩衝區管理 API 可讓您進行不同類型的緩衝區管理 適合執行的策略例如:

  • 回溯相容:擷取要求的 HAL 要求緩衝區 在 processCaptureRequest 呼叫期間執行此步驟這項策略不提供 節省記憶體,但可做為緩衝區的第一次實作 Management API,只需極少修改現有相機 HAL 的程式碼即可。
  • 盡可能節省記憶體:相機 HAL 僅要求輸出緩衝區 才會填入廣告這項策略能讓 最大記憶體節省量潛在的缺點是增加相機管道 當緩衝區要求完成異常長時,就會卡頓。
  • 快取:相機 HAL 會快取一些緩衝區,降低 可能會受到暫時性的緩衝要求影響

相機 HAL 可以針對特定用途採用不同策略, 例如,針對大量使用情境,使用最大記憶體節省策略 記憶體用量,並針對其他用途使用回溯相容策略。

外部相機 HAL 中的實作範例

外接式相機 HAL 是在 Android 9 中推出,可在 來源樹狀結構 hardware/interfaces/camera/device/3.5/。 Android 10 已更新,現在加入了 ExternalCameraDeviceSession.cpp、 緩衝管理 API 的實作。這部外接鏡頭 HAL 採行「緩衝區管理」中所述的最大記憶體節省策略 採用這些策略 C++ 程式碼。