裝置製造商可透過原始設備製造商 (OEM) 供應商程式庫提供的相機擴充功能介面,向第三方開發人員公開散景、夜間模式和 HDR 等擴充功能。開發人員可以使用 Camera2 Extensions API 和 CameraX Extensions API,存取 OEM 供應商程式庫中實作的擴充功能。
如需支援的擴充功能清單 (在 Camera2 和 CameraX 中相同),請參閱 CameraX Extensions API。如要新增擴充功能,請透過 Issue Tracker 回報錯誤。
本頁面說明如何在裝置上實作及啟用 OEM 供應商程式庫。
建築
下圖說明相機擴充功能介面或 extensions-interface
的架構:
圖 1. 相機擴充功能架構圖
如圖所示,如要支援相機擴充功能,您必須實作 OEM 供應商程式庫提供的 extensions-interface
。OEM 供應商程式庫會啟用兩個 API:CameraX Extensions API 和 Camera2 Extensions API,分別由 CameraX 和 Camera2 應用程式用來存取供應商擴充功能。
導入原始設備製造商 (OEM) 供應商程式庫
如要實作 OEM 供應商程式庫,請將 camera-extensions-stub
檔案複製到系統程式庫專案中。這些檔案會定義相機擴充功能介面。
camera-extensions-stub
檔案分為以下類別:
必要介面檔案 (請勿修改)
PreviewExtenderImpl.java
ImageCaptureExtenderImpl.java
ExtenderStateListener.java
ProcessorImpl.java
PreviewImageProcessorImpl.java
CaptureProcessorImpl.java
CaptureStageImpl.java
RequestUpdateProcessorImpl.java
ProcessResultImpl.java
advanced/AdvancedExtenderImpl.java
advanced/Camera2OutputConfigImpl.java
advanced/Camera2SessionConfigImpl.java
advanced/ImageProcessorImpl.java
advanced/ImageReaderOutputConfigImpl.java
advanced/ImageReferenceImpl.java
advanced/MultiResolutionImageReaderOutputConfigImpl.java
advanced/OutputSurfaceImpl.java
advanced/RequestProcessorImpl.java
advanced/SessionProcessorImpl.java
advanced/SurfaceOutputConfigImpl.java
必要實作 (新增實作)
ExtensionVersionImpl.java
InitializerImpl.java
Bokeh 擴充工具類別 (如果支援 Bokeh 擴充功能,即可實作)
BokehImageCaptureExtenderImpl.java
BokehPreviewExtenderImpl.java
advanced/BokehAdvancedExtenderImpl.java
夜間延長器類別 (如果支援夜間延長器,請實作這個類別)
NightImageCaptureExtenderImpl.java
NightPreviewExtenderImpl.java
advanced/NightAdvancedExtenderImpl.java
自動延伸類別 (如果支援自動延伸功能,請實作此類別)
AutoImageCaptureExtenderImpl.java
AutoPreviewExtenderImpl.java
advanced/AutoAdvancedExtenderImpl.java
HDR 擴充器類別 (在支援 HDR 擴充功能時實作)
HdrImageCaptureExtenderImpl.java
HdrPreviewExtenderImpl.java
advanced/HdrAdvancedExtenderImpl.java
修容擴充功能類別 (如果支援 Face Retouch 擴充功能,即可實作)
BeautyImageCaptureExtenderImpl.java
BeautyPreviewExtenderImpl.java
advanced/BeautyAdvancedExtenderImpl.java
公用程式 (選用,可刪除)
advanced/Camera2OutputConfigImplBuilder.java
advanced/Camera2SessionConfigImplBuilder.java
您不需要為每個擴充功能提供實作項目。如果您未實作擴充功能,請將 isExtensionAvailable()
設為傳回 false
,或移除對應的 Extender 類別。Camera2 和 CameraX Extensions API 會向應用程式回報擴充功能無法使用。
以下逐步說明 Camera2 和 CameraX Extensions API 如何與廠商程式庫互動,藉此啟用擴充功能。下圖以 Night 擴充功能為例,說明端對端流程:
圖 2. 夜間擴充功能實作
版本驗證:
Camera2/X 會呼叫
ExtensionVersionImpl.checkApiVersion()
,確保 OEM 實作的extensions-interface
版本與 Camera2/X 支援的版本相容。供應商程式庫初始化:
InitializerImpl
有一個用於初始化供應商程式庫的方法init()
。Camera2/X 會先完成初始化,接著再存取延伸器類別。例項化 Extender 類別:
為擴充功能例項化 Extender 類別。擴充功能有兩種類型:基本擴充功能和進階擴充功能。您必須為所有擴充功能實作一個擴充功能類型。詳情請參閱「基本擴充功能與進階擴充功能」。
Camera2/X 會將 Extender 類別例項化並與其互動,以便擷取資訊並啟用擴充功能。針對特定擴充功能,Camera2/X 可以多次將 Extender 類別例項化。因此,請勿在建構函式或
init()
呼叫中執行繁重的工作初始化作業。只有在相機工作階段即將開始時才執行繁重的工作,例如在基本擴充功能中呼叫onInit()
,或在進階擴充功能中呼叫initSession()
。針對 Night 擴充功能,系統會針對 Basic Extender 類型例項化下列 Extender 類別:
NightImageCaptureExtenderImpl.java
NightPreviewExtenderImpl.java
進階擴展器類型則:
NightAdvancedExtenderImpl.java
檢查擴充功能的可用性:
啟用擴充功能前,
isExtensionAvailable()
會透過 Extender 例項,檢查指定相機 ID 是否可使用擴充功能。使用相機資訊將延伸器初始化:
Camera2/X 會在 Extender 例項上呼叫
init()
,並傳遞相機 ID 和CameraCharacteristics
。查詢資訊:
叫用 Extender 類別,擷取支援的解析度等資訊、仍擷取預估延遲時間,並從 Extender 擷取要求索引鍵,以便準備啟用擴充功能。
在擴充機器上啟用擴充功能:
Extender 類別會提供啟用類別所需的所有介面。這個程式庫提供將原始設備製造商 (OEM) 實作連結至 Camera2 管道的機制,例如插入擷取要求參數或啟用後置處理器。
對於進階延伸器類型,Camera2/X 會與
SessionProcessorImpl
互動,啟用擴充功能。Camera2/X 會在 Extender 上呼叫createSessionProcessor()
,藉此擷取SessionProcessorImpl
例項。
以下各節將詳細說明擴充功能流程。
版本驗證
在執行階段從裝置載入 OEM 供應商程式庫時,Camera2/X 會驗證該程式庫是否與 extensions-interface
版本相容。extensions-interface
使用語意化版本,也就是 MAJOR.MINOR.PATCH,例如 1.1.0 或 1.2.0。不過,驗證版本時只會使用主要和次要版本。
如要驗證版本,Camera2/X 會使用支援的 extensions-interface
版本呼叫 ExtensionVersionImpl.checkApiVersion()
。接著,Camera2/X 會使用 OEM 程式庫回報的版本,判斷是否可以啟用擴充功能,以及該擴充功能應叫用哪些功能。
主要版本相容性
如果 extension-interface 的主要版本在 Camera2/X 和供應商程式庫之間不同,系統會將其視為「不相容」,因此會停用擴充功能。
回溯相容性
只要主要版本相同,Camera2/X 就會確保與以先前 extensions-interface
版本建構的 OEM 供應商程式庫回溯相容性。舉例來說,如果 Camera2/X 支援 extensions-interface
1.3.0,實作 1.0.0、1.1.0 和 1.2.0 的 OEM 供應商程式庫仍可相容。這也表示,在您實作供應商程式庫的特定版本後,Camera2/X 會確保該程式庫與即將推出的 extension-interface
版本相容。
前瞻相容性
新版 extensions-interface
與供應商程式庫的向前相容性取決於 OEM。如果您需要一些功能來實作擴充功能,建議您從特定版本開始啟用擴充功能。在這種情況下,如果 Camera2/X 程式庫版本符合需求,您可以傳回支援的 extensions-interface
版本。如果不支援 Camera2/X 版本,您可以傳回不相容的版本 (例如 99.0.0),藉此停用擴充功能。
供應商程式庫初始化
驗證 OEM 程式庫實作的 extensions-interface
版本後,Camera2/X 就會啟動初始化程序。InitializerImpl.init()
方法會向 OEM 程式庫發出信號,指出應用程式嘗試使用擴充功能。
在 OEM 供應商程式庫呼叫 OnExtensionsInitializedCallback.onSuccess()
通知初始化完成之前,Camera2/X 不會對 OEM 程式庫進行其他呼叫 (除了版本檢查)。
您必須從 extensions-interface
1.1.0 版開始實作 InitializerImpl
。如果 OEM 供應商程式庫實作 extensions-interface
1.0.0,Camera2/X 會略過程式庫初始化步驟。
基本延伸功能與進階延伸功能
extensions-interface
實作方式分為兩種:基本擴充功能和進階擴充功能。extensions-interface
1.2.0 以上版本支援進階延伸功能。
實作基本擴充功能,用於在相機 HAL 中處理圖片,或使用可處理 YUV 串流的後置處理器。
針對需要自訂 Camera2 串流設定及傳送擷取要求的擴充功能,實作進階擴充程式。
請參閱下表的比較結果:
基本延伸器 | 進階延伸功能 | |
---|---|---|
串流設定 | 已修正 預覽: PRIVATE 或 YUV_420_888 (如有處理器) 仍擷取: JPEG 或 YUV_420_888 (如有處理器) |
可由原始設備製造商 (OEM) 自訂。 |
傳送擷取要求 | 只有 Camera2/X 可以傳送擷取要求。您可以為這些要求設定參數。當提供處理器用於擷取圖片時,Camera2/X 可以傳送多個擷取要求,並將所有圖片和擷取結果傳送至處理器。 | 系統會提供 RequestProcessorImpl 例項,讓您執行 Camera2 擷取要求,並取得結果和圖片。
Camera2/X 會在 |
相機管道中的鉤子 |
|
|
適合 | 在相機 HAL 或處理 YUV 圖片的處理器中實作的擴充功能。 |
|
支援的 API 版本 | Camera2 Extensions:Android 13 以上版本 CameraX Extensions: camera-extensions 1.1.0 以上版本 |
Camera2 Extensions:Android 12L 以上版本 CameraX Extensions: camera-extensions 1.2.0-alpha03 以上版本 |
應用程式流程
下表列出三種應用程式流程和相應的 Camera Extensions API 呼叫。雖然 Camera2/X 提供這些 API,但您必須正確實作供應商程式庫,才能支援這些流程,我們會在後續章節中詳細說明。
Camera2 擴充功能 | CameraX 擴充功能 | |
---|---|---|
查詢擴充功能適用情形 | CameraExtensionCharacteristics
.getSupportedExtensions
|
ExtensionsManager.
isExtensionAvailable
|
查詢資訊 | CameraExtensionCharacteristics.
getExtensionSupportedSizes
CameraExtensionCharacteristics.
getEstimatedCaptureLatencyRangeMillis
CameraExtensionCharacteristics.
getAvailableCaptureRequestKeys
CameraExtensionCharacteristics.
getAvailableCaptureResultKeys
|
ExtensionsManager.
getEstimatedCaptureLatencyRange
CameraX 會處理程式庫中的其他資訊。 |
在啟用擴充功能的情況下預覽及靜態拍攝 | CameraDevice.
createExtensionSession
|
val cameraSelector = ExtensionsManager.
getExtensionEnabledCameraSelector
|
基本延長線
基本擴充介面會在相機管道中的多個位置提供鉤子。每個擴充功能類型都有對應原始設備製造商 (OEM) 需實作的擴充工具類別。
下表列出 OEMS 為每個擴充功能實作的擴充器類別:
要實作的擴充類別 | |
---|---|
夜晚 | NightPreviewExtenderImpl.java
|
HDR | HdrPreviewExtenderImpl.java
|
自動 | AutoPreviewExtenderImpl.java
|
Bokeh | BokehPreviewExtenderImpl.java
|
修容 | BeautyPreviewExtenderImpl.java
|
在以下範例中,我們使用 PreviewExtenderImpl
和 ImageCaptureExtenderImpl
做為預留位置。請將這些名稱替換為您要實作的實際檔案名稱。
基本擴充功能提供下列功能:
- 設定
CameraCaptureSession
(onPresetSession
) 時,請插入工作階段參數。 - 通知您擷取工作階段的開始和結束事件,並傳送單一要求,以便通知 HAL 傳回的參數 (
onEnableSession
、onDisableSession
)。 - 為要求插入擷取參數 (
PreviewExtenderImpl.getCaptureStage
、ImageCaptureExtenderImpl.getCaptureStages
)。 - 新增可處理
YUV_420_888
串流的預覽和靜態擷取處理器。
讓我們看看 Camera2/X 如何叫用 extensions-interface
,以實現上述三個應用程式流程。
應用程式流程 1:檢查擴充功能的可用性
圖 3. 在 Basic Extender 上執行應用程式流程 1
在這個流程中,Camera2/X 會直接呼叫 PreviewExtenderImpl
和 ImageCaptureExtenderImpl
的 isExtensionAvailable()
方法,但不會呼叫 init()
。兩個延伸類別都必須傳回 true
,才能啟用擴充功能。
這通常是應用程式必須先檢查特定相機 ID 是否支援指定的擴充功能類型,再啟用該擴充功能。這是因為部分擴充功能僅支援特定相機 ID。
應用程式流程 2:查詢資訊
圖 4. 在基本擴充功能上執行應用程式流程 2
確定是否可使用擴充功能後,應用程式應先查詢下列資訊,再啟用擴充功能。
靜態影像擷取延遲範圍:
ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
會傳回擷取延遲範圍,讓應用程式評估是否適合在目前情境中啟用擴充功能。預覽和擷取途徑支援的大小:
ImageCaptureExtenderImpl.getSupportedResolutions
和PreviewExtenderImpl.getSupportedResolutions
會傳回圖像格式清單,以及途徑格式和大小支援的大小。支援的要求和結果鍵:Camera2/X 會叫用下列方法,從實作中擷取支援的擷取要求金鑰和結果鍵:
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
ImageCaptureExtenderImpl.getAvailableCapturetResultKeys
Camera2/X 一律會先對這些擴充器類別呼叫 init()
,然後再查詢更多資訊。
應用程式流程 3:啟用擴充功能的預覽/靜態影像擷取 (HAL 實作)
圖 5. 在 Basic Extender 上執行應用程式流程 3
上圖說明在沒有任何處理器的情況下,透過擴充功能啟用預覽和靜態影像擷取功能的主要流程。也就是說,相機 HAL 會處理擴充功能。
在這個流程中,Camera2/X 會先呼叫 init()
,然後再呼叫 onInit
,以便通知您,相機工作階段即將以指定的擴充功能開始。您可以在 onInit()
中進行大量初始化作業。
設定 CameraCaptureSession
時,Camera2/X 會叫用 onPresetSession
來取得工作階段參數。擷取工作階段設定成功後,Camera2/X 會叫用 onEnableSession
,傳回包含擷取參數的 CaptureStageImpl
例項。Camera2/X 會立即傳送含有這些擷取參數的單一要求,通知 HAL。同樣地,在擷取工作階段關閉之前,Camera2/X 會叫用 onDisableSession
,然後傳送包含傳回擷取參數的單一要求。
由 Camera2/X 觸發的重複要求包含 PreviewExtenderImpl.getCaptureStage()
傳回的要求參數。此外,靜態影像擷取要求包含 ImageCaptureExtenderImpl.getCaptureStages()
傳回的參數。
最後,在相機工作階段結束後,Camera2/X 會叫用 onDeInit()
。您可以在 onDeinit()
中釋出資源。
預覽處理器
除了攝影機 HAL 之外,您也可以在處理器中實作擴充功能。
如要指定處理器類型,請實作 PreviewExtenderImpl.getProcessorType
,如下所述:
PROCESSOR_TYPE_NONE
:無處理器。圖片會在相機 HAL 中處理。PROCESSOR_TYPE_REQUEST_UPDATE_ONLY
:處理器類型可讓您根據最新的TotalCaptureResult
,使用新的擷取要求參數更新重複要求。PreviewExtenderImpl.getProcessor
必須傳回處理TotalCaptureResult
例項的RequestUpdateProcessorImpl
執行個體,並傳回CaptureStageImpl
例項,以更新重複要求。PreviewExtenderImpl.getCaptureStage()
也應反映處理結果,並傳回最新的CaptureStageImpl
。PROCESSOR_TYPE_IMAGE_PROCESSOR
:這個類型可讓您實作處理器來處理YUV_420_888
圖片,並將輸出內容寫入PRIVATE
介面。您必須在
PreviewExtenderImpl.getProcessor
中實作並傳回PreviewImageProcessorImpl
例項。處理器負責處理YUV_420_888
輸入圖片。指令應該會將輸出內容寫入預覽的PRIVATE
格式。Camera2/X 會使用YUV_420_888
介面,而非PRIVATE
,設定用於預覽的CameraCaptureSession
。請參閱以下流程插圖:
圖 6. 使用 PreviewImageProcessorImpl
預覽流程
PreviewImageProcessorImpl
介面會擴充 ProcessImpl
,並提供三個重要方法:
onOutputSurface(Surface surface, int imageFormat)
會為處理器設定輸出表面。對於PreviewImageProcessorImpl
,imageFormat
是像素格式,例如PixelFormat.RGBA_8888
。onResolutionUpdate(Size size)
會設定輸入圖片的大小。onImageFormatUpdate(int imageFormat)
會設定輸入圖片的圖片格式。目前只能是YUV_420_888
。
圖片擷取處理器
如要繼續擷取,您可以使用 ImageCaptureExtenderImpl.getCaptureProcessor
傳回 CaptureProcessorImpl
執行個體,實作處理器。處理器負責處理擷取的 YUV_420_888
圖片和 TotalCaptureResult
例項清單,並將輸出內容寫入 YUV_420_888
介面。
您可以在傳送仍在擷取要求之前,放心假設預覽已經啟用並執行。
請參閱下圖中的流程:
圖 7. 仍可透過 CaptureProcessorImpl
擷取流程
Camera2/X 會使用
YUV_420_888
格式介面進行靜態擷取來設定擷取工作階段。Camera2/X 會透過呼叫以下項目來準備CaptureProcessorImpl
:CaptureProcessorImpl.onImageFormatUpdate()
與YUV_420_888
。CaptureProcessorImpl.onResolutionUpdate()
與輸入圖片大小。CaptureProcessorImpl.onOutputSurface()
與輸出YUV_420_888
介面。
ImageCaptureExtenderImpl.getCaptureStages
會傳回CaptureStageImpl
的清單,其中每個元素會對應至CaptureRequest
例項,並包含由 Camera2/X 傳送的擷取參數。舉例來說,如果它傳回三個CaptureStageImpl
例項的清單,Camera2/X 會使用captureBurst
API 傳送三個擷取要求,並附上對應的擷取參數。系統會將收到的圖片和
TotalCaptureResult
例項綁在一起,並傳送至CaptureProcessorImpl
進行處理。CaptureProcessorImpl
會將結果圖片 (YUV_420_888
格式) 寫入onOutputSurface()
呼叫指定的輸出途徑。必要時,Camera2/X 會將其轉換為 JPEG 圖片。
支援擷取要求鍵和結果
除了相機預覽和擷取功能外,應用程式還可以設定縮放、閃光燈參數,或觸發輕觸對焦功能。這些參數可能與擴充功能的實作方式不相容。
以下方法已新增至 extensions-interface
1.3.0,讓您公開實作項目支援的參數:
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys()
會傳回您的實作支援的擷取要求金鑰。ImageCaptureExtenderImpl.getAvailableCaptureResultKeys()
會傳回擷取結果中包含的擷取結果鍵。
如果相機 HAL 處理擴充功能,Camera2/X 會在 CameraCaptureSession.CaptureCallback
中擷取結果。不過,如果已實作處理器,Camera2/X 會在 ProcessResultImpl
中擷取擷取結果,並將該結果傳遞至 PreviewImageProcessorImpl
和 CaptureProcessorImpl
中的 process()
方法。您必須負責透過 ProcessResultImpl
將擷取結果回報給 Camera2/X。
請參考下方的 CaptureProcessorImpl
介面定義範例。在 extensions-interface
1.3.0 以上版本中,會叫用第二個 process()
呼叫:
Interface CaptureProcessorImpl extends ProcessorImpl {
// invoked when extensions-interface version < 1.3.0
void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
// invoked when extensions-interface version >= 1.3.0
void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor);
}
針對縮放、輕觸對焦、閃光燈和曝光補償等常見的相機作業,建議您同時支援以下按鍵來擷取要求和拍攝結果:
- Zoom:
CaptureRequest#CONTROL_ZOOM_RATIO
CaptureRequest#SCALER_CROP_REGION
- 輕觸對焦:
CaptureRequest#CONTROL_AF_MODE
CaptureRequest#CONTROL_AF_TRIGGER
CaptureRequest#CONTROL_AF_REGIONS
CaptureRequest#CONTROL_AE_REGIONS
CaptureRequest#CONTROL_AWB_REGIONS
- Flash:
CaptureRequest#CONTROL_AE_MODE
CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
CaptureRequest#FLASH_MODE
- 曝光補償:
CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
對於實作 1.2.0 以上版本的基本擴充功能,CameraX Extensions API 會明確支援上述所有鍵。對於 extensions-interface
1.3.0,CameraX 和 Camera2 都會遵循傳回的清單,且只支援其中包含的鍵。舉例來說,如果您決定在 1.3.0 實作中只傳回 CaptureRequest#CONTROL_ZOOM_RATIO
和 CaptureRequest#SCALER_CROP_REGION
,表示應用程式只支援縮放,但不支援輕觸對焦、閃光燈和曝光補償。
進階延伸功能
進階擴充功能是一種以 Camera2 API 為基礎的供應商實作項目。這個延伸元件類型已在 extensions-interface
1.2.0 中新增。視裝置製造商而定,擴充功能可能會在應用程式層中實作,這取決於下列因素:
自訂串流設定:設定 RAW 串流等自訂串流,或為不同的實體相機 ID 設定多個串流。
傳送 Camera2 要求的能力:支援複雜的互動邏輯,可根據先前要求的結果傳送帶有參數的擷取要求。
進階延伸元件會提供包裝函式或中介層,讓您自訂串流設定,並視需要傳送擷取要求。
要實作的檔案
如要切換至進階擴充功能實作項目,ExtensionVersionImpl
中的 isAdvancedExtenderImplemented()
方法必須傳回 true
。針對每種擴充功能類型,原始設備製造商 (OEM) 必須實作對應的擴展器類別。進階擴充功能導入檔案位於「進階」套件中。
要實作的擴充類別 | |
---|---|
夜晚 | advanced/NightAdvancedExtenderImpl.java
|
HDR | advanced/HdrAdvancedExtenderImpl.java
|
自動 | advanced/AutoAdvancedExtenderImpl.java
|
Bokeh | advanced/BokehAdvancedExtenderImpl.java
|
修容 | advanced/BeautyAdvancedExtenderImpl.java
|
在以下範例中,我們使用 AdvancedExtenderImpl
做為預留位置。請將其替換為要實作的擴充功能的 Extender 檔案名稱。
現在來看看 Camera2/X 如何叫用 extensions-interface
來完成三個應用程式流程。
應用程式流程 1:檢查擴充功能的可用性
圖 8. 進階擴展器上的應用程式流程 1
首先,應用程式會檢查是否支援指定的擴充功能。
應用程式流程 2:查詢資訊
圖 9.進階擴展器的應用程式流程 2
呼叫 AdvancedExtenderImpl.init()
後,應用程式可查詢 AdvancedExtenderImpl
的下列資訊:
預估仍會擷取延遲時間:
AdvancedExtenderImpl.getEstimatedCaptureLatencyRange()
會傳回擷取延遲時間的範圍,讓應用程式評估是否能在目前情境中啟用擴充功能。預覽和靜態擷取支援的解析度:
AdvancedExtenderImpl.getSupportedPreviewOutputResolutions()
會將圖片格式對應至預覽途徑格式和大小的支援大小清單。原始設備製造商 (OEM) 至少必須支援PRIVATE
格式。AdvancedExtenderImpl.getSupportedCaptureOutputResolutions()
會傳回靜態擷取途徑支援的格式和大小。原始設備製造商必須同時支援JPEG
和YUV_420_888
格式的輸出內容。AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()
會傳回圖像分析的額外YUV_420_888
串流支援的大小。如果系統不支援圖像分析 YUV 途徑,getSupportedYuvAnalysisResolutions()
應傳回null
或空白清單。
可用的擷取要求鍵/結果 (在
extensions-interface
1.3.0 中新增):Camera2/X 會叫用下列方法,從實作中擷取支援的擷取要求鍵和結果鍵:AdvancedExtenderImpl.getAvailableCaptureRequestKeys
AdvancedExtenderImpl.getAvailableCaptureResultKeys
詳情請參閱「支援擷取要求索引鍵和結果」。
應用程式流程 3:啟用擴充功能的預覽/靜態影像擷取
圖 10. 進階擴展器的應用程式流程 3
上圖顯示進階延伸器類型開始預覽和靜態擷取的主要流程。接下來,我們將逐步說明各個步驟。
SessionProcessorImpl
執行個體核心進階擴充功能實作項目位於
SessionProcessorImpl
中,負責提供自訂的工作階段設定,並傳送擷取要求,以便啟動預覽和靜態擷取要求。系統會叫用AdvancedExtenderImpl.createSessionProcessor()
來傳回SessionProcessorImpl
例項。initSession
SessionProcessorImpl.initSession()
會初始化擴充功能的工作階段。您可以在這裡分配資源,並傳回工作階段設定來準備CameraCaptureSession
。針對輸入參數,Camera2/X 會指定預覽、靜態影像擷取和選用的 YUV 圖片分析的輸出介面設定。這個輸出途徑設定 (
OutputSurfaceImpl
) 包含途徑、大小和圖片格式,這些資訊是透過AdvancedExtenderImpl
中的下列方法擷取:getSupportedPreviewOutputResolutions()
getSupportedCaptureOutputResolutions()
getSupportedYuvAnalysisResolutions()
您必須傳回
Camera2SessionConfigImpl
執行個體,其中包含Camera2OutputConfigImpl
執行個體的清單,以及設定CameraCaptureSession
的工作階段參數。您必須負責將正確的相機影像輸出到 Camera2/X 傳入的輸出介面。以下列舉幾個啟用輸出的選項:- 在相機 HAL 中處理:您可以直接使用
SurfaceOutputConfigImpl
實作,將輸出途徑新增至CameraCaptureSession
。這會設定為相機管道提供的輸出介面,並允許相機 HAL 處理圖片。 處理中繼
ImageReader
介面 (RAW、YUV 等):使用ImageReaderOutputConfigImpl
例項將中繼ImageReader
介面新增至CameraCaptureSession
。您必須處理中繼圖片,並將結果圖片寫入輸出介面。
- 使用 Camera2 途徑共用功能:將任何
Camera2OutputConfigImpl
例項新增至其他Camera2OutputConfigImpl
例項的getSurfaceSharingOutputConfigs()
方法,即可使用途徑共用功能與其他途徑。表面格式和大小必須相同。
包括
SurfaceOutputConfigImpl
和ImageReaderOutputConfigImpl
等所有Camera2OutputConfigImpl
都必須有專屬 ID (getId()
),用於指定目標介面並從ImageReaderOutputConfigImpl
擷取圖片。onCaptureSessionStart
和RequestProcessorImpl
當
CameraCaptureSession
啟動且相機架構叫用onConfigured()
時,Camera2/X 就會使用 Camera2 要求包裝函式RequestProcessImpl
叫用SessionProcessorImpl.onCaptureSessionStart()
。Camera2/X 會實作RequestProcessImpl
,讓您執行擷取要求,並在使用ImageReaderOutputConfigImpl
時擷取圖片。RequestProcessImpl
API 在執行要求方面與 Camera2CameraCaptureSession
API 類似。兩者之間的差異如下:- 目標途徑會透過
Camera2OutputConfigImpl
例項的 ID 指定。 - 可擷取
ImageReader
的圖片。
您可以使用指定的
Camera2OutputConfigImpl
ID 呼叫RequestProcessorImpl.setImageProcessor()
,以便註冊ImageProcessorImpl
執行個體來接收圖片。在 Camera2/X 呼叫
SessionProcessorImpl.onCaptureSessionEnd()
後,RequestProcessImpl
例項就會失效。- 目標途徑會透過
開始預覽並拍照
在進階擴充功能實作中,您可以透過
RequestProcessorImpl
介面傳送擷取要求。Camera2/X 會分別呼叫SessionProcessorImpl#startRepeating
和SessionProcessorImpl#startCapture
,通知您開始重複要求預覽畫面或靜止影像擷取序列。您應傳送擷取要求,以滿足這些預覽和靜態擷取要求。Camera2/X 也會透過
SessionProcessorImpl#setParameters
設定擷取要求參數。您必須在重複和單一要求中設定這些要求參數 (如果系統支援參數)。您必須至少支援
CaptureRequest.JPEG_ORIENTATION
和CaptureRequest.JPEG_QUALITY
。extensions-interface
1.3.0 支援要求和結果鍵,這些鍵會透過下列方法公開:AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
AdvancedExtenderImpl.getAvailableCaptureResultKeys()
開發人員在
getAvailableCaptureRequestKeys
清單中設定鍵時,必須啟用參數,並確保擷取結果包含getAvailableCaptureResultKeys
清單中的鍵。startTrigger
系統會叫用
SessionProcessorImpl.startTrigger()
來啟動觸發事件,例如CaptureRequest.CONTROL_AF_TRIGGER
和CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER
。您可以忽略AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
中未宣傳的任何擷取要求鍵。extensions-interface
1.3.0 版起支援startTrigger()
。這項功能可讓應用程式透過擴充功能實作輕觸對焦和閃光效果。清理
完成擷取工作階段時,系統會在
CameraCaptureSession
關閉前叫用SessionProcessorImpl.onCaptureSessionEnd()
。擷取工作階段關閉後,deInitSession()
會執行清理作業。
支援預覽、靜態擷取和圖片分析功能
您應為預覽和靜態影像拍攝用途套用擴充功能。不過,如果延遲時間太高,無法流暢顯示預覽,您可以將擴充功能套用於仍方便擷取的情況。
對於基本擴充功能類型,無論是否啟用預覽擴充功能,您都必須為特定擴充功能實作 ImageCaptureExtenderImpl
和 PreviewExtenderImpl
。應用程式通常也會使用 YUV 串流來分析圖片內容,例如尋找 QR code 或文字。為進一步支援此用途,您應支援預覽、靜態影像擷取和 YUV_420_888
串流的串流組合,以便設定 CameraCaptureSession
。也就是說,如果您實作處理器,就必須支援三個 YUV_420_888
串流的串流組合。
對於進階擴充功能,Camera2/X 會將三個輸出途徑傳遞至 SessionProcessorImpl.initSession()
呼叫。這些輸出介面分別用於預覽、靜態擷取和圖片分析。您必須確保預覽且仍可擷取輸出介面,顯示有效的輸出內容。但是,如果是圖片分析輸出介面,請確保只有非空值時才能正常運作。如果您的實作不支援圖片分析串流,您可以在 AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()
中傳回空白清單。這可確保圖片分析輸出介面在 SessionProcessorImpl.initSession()
中一律為空值。
支援錄影
目前的 CameraX 擴充功能架構僅支援預覽和靜態影像拍攝用途。我們不支援在 MediaCodec
或 MediaRecorder
途徑上啟用擴充功能來錄製影片。不過,應用程式可以記錄預覽輸出內容。
我們正在研究如何支援 MediaCodec
和 MediaRecorder
介面。
擴充功能專屬中繼資料
在 Android 14 以上版本中,擴充功能專屬的媒體資料可讓相機擴充功能用戶端設定及接收擴充功能專屬的擷取要求設定和結果。具體來說,相機擴充功能用戶端可使用 EXTENSION_STRENGTH
擷取要求參數控制擴充功能強度,並使用 EXTENSION_CURRENT_TYPE
擷取結果指示已啟用的擴充功能類型。
擷取要求
EXTENSION_STRENGTH
擷取要求參數可控制擴充功能後續處理效果的強度。如果用戶端未明確設定此參數,對應的擷取結果就會包含預設強度值。針對下列擴充功能類型,這個參數可套用如下方式:
BOKEH
:控制模糊程度。HDR
和NIGHT
:控制融合的圖片量,以及最終圖片的亮度。FACE_RETOUCH
:控制美容強化和皮膚平滑效果的程度。
EXTENSION_STRENGTH
參數支援的範圍介於 0
和 100
之間,其中 0
表示沒有擴充處理或簡單的直通,而 100
則表示處理效果的最大擴充強度。
如要新增 EXTENSION_STRENGTH
支援功能,請使用擴充資料庫介面 1.3.0 版中推出的供應商專屬參數 API。詳情請參閱 getAvailableCaptureRequestKeys()
。
擷取結果
EXTENSION_CURRENT_TYPE
擷取結果可讓擴充功能實作通知用戶端目前的擴充功能類型。
使用 AUTO
類型的擴充功能會根據情境條件,在 HDR
和 NIGHT
等擴充功能類型之間動態切換,因此相機擴充功能應用程式可以使用 EXTENSION_CURRENT_TYPE
,顯示 AUTO
擴充功能所選目前擴充功能的相關資訊。
即時靜態影像擷取延遲時間估計值
在 Android 14 以上版本中,攝影機擴充功能用戶端可以使用 getRealtimeStillCaptureLatency()
,根據場景和環境條件查詢即時靜態影像擷取延遲時間的預估值。這個方法提供的預估值比靜態 getEstimatedCaptureLatencyRangeMillis()
方法更準確。根據估計的延遲時間,應用程式可以決定略過擴充功能處理,或顯示指示使用者以通知長時間執行的作業。
CameraExtensionSession.StillCaptureLatency latency;
latency = extensionSession.getRealtimeStillCaptureLatency();
// The capture latency from ExtensionCaptureCallback#onCaptureStarted() until ExtensionCaptureCallback#onCaptureProcessStarted().
latency.getCaptureLatency();
// The processing latency from ExtensionCaptureCallback#onCaptureProcessStarted() until the processed frame returns to the client.
latency.getProcessingLatency();
如要支援即時靜態影像擷取延遲時間估計,請實作以下項目:
- 基本額外資訊:
ImageCaptureExtenderImpl.getRealtimeCaptureLatency()
- 進階擴充功能:
SessionProcessorImpl.getRealtimeCaptureLatency
擷取影像處理進度回呼
如果是 Android 14 或以上版本,相機擴充功能用戶端可以接收長時間執行進度的回呼,但仍會擷取處理作業。應用程式可以向使用者顯示目前進度,改善整體使用者體驗。
應用程式可使用以下程式碼整合這項功能:
import android.hardware.camera2.CameraExtensionSession.
ExtensionCaptureCallback;
{
…
class AppCallbackImpl extends ExtensionCaptureCallback {
…
@Override
public void onCaptureProcessProgressed(
@NonNull CameraExtensionSession session,
@NonNull CaptureRequest request,
@IntRange(from = 0, to = 100) int progress) {
// Update app UI with current progress
}
}
…
}
如要支援擷取處理進度回呼,擴充功能供應商實作項目必須使用目前的進度值呼叫下列回呼:
- 基本額外資訊:
ProcessResultImpl.onCaptureProcessProgressed()
- 進階額外資訊:
CaptureCallback.onCaptureProcessProgressed()
瀏覽後動作靜態擷圖
對於 Android 14 以上版本,相機擴充功能可以使用 setPostviewOutputConfiguration
提供後視圖 (預覽圖片)。為了改善使用者體驗,當擴充功能遇到的處理延遲時間增加時,應用程式可將後畫面圖片顯示為預留位置,並在最終圖片可用時替換圖片。應用程式可以使用以下參考代碼設定並發出瀏覽後轉換擷取要求:
{
…
if (!CameraExtensionCharacteristics.isPostviewAvailable()) {
continue;
}
…
ExtensionSessionConfiguration extensionConfiguration = new
ExtensionSessionConfiguration(
CameraExtensionCharacteristics.EXTENSION_NIGHT,
outputConfig,
backgroundExecutor,
extensionSessionStateCallback
);
extensionConfiguration.setPostviewOutputConfiguration(
postviewImageOutput);
…
CaptureRequest.Builder captureRequestBuilder =
cameraDevice.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(stillImageReader.getSurface());
captureRequestBuilder.addTarget(postviewImageSurface);
CaptureRequest captureRequest = captureRequestBuilder.build();
…
}
如要支援後見影像擷取功能,您的供應商導入方式必須實作下列項目:
支援 SurfaceView 輸出
如果是 Android 14 以上版本,相機擴充功能用戶端可以為重複要求註冊 SurfaceView
執行個體,用於預覽輸出,藉此使用電源和效能最佳化的預覽轉譯路徑。
如要支援 SurfaceView
輸出,廠商擴充功能實作必須能夠串流及輸出預覽至 SurfaceView
執行個體。如要確認是否支援此功能,請執行 SurfaceViewExtensionPreviewTest.java
CTS 模組。
供應商專屬的工作階段類型
這項功能可讓供應商擴充功能實作選取供應商專屬的工作階段類型,並在內部相機擷取工作階段中設定該類型,而非預設值。
這項功能完全在架構和供應商堆疊中運作,不會對用戶端/公開 API 造成影響。
如要選取特定廠商的工作階段類型,請為擴充資料程式庫實作以下項目:
* 基本擴充資料的 ExtenderStateListener.onSessionType()
* 進階擴充資料的 Camera2SessionConfigImpl.getSessionType()
擴充功能介面版本記錄
下表顯示相機擴充功能介面版本記錄。您應一律使用最新版本的供應商程式庫。
版本 | 新增功能 |
---|---|
1.0.0 |
|
1.1.0 |
|
1.2.0 |
|
1.3.0 |
|
1.4.0 |
|
參考實作
frameworks/ex
提供下列參考 OEM 供應商程式庫實作項目。
advancedSample
:進階延伸模組的基本實作。sample
:基本擴充程式的基本實作。service_based_sample
:示範如何在Service
中託管相機擴充功能的實作。這個實作包含下列元件:oem_library
:適用於 Camera2 和 CameraX Extensions API 的 Camera Extensions OEM 程式庫,可實作Extensions-Interface
。這會做為暫時允許手勢,將Extensions-Interface
的呼叫轉送至服務。這個程式庫也會提供 AIDL 檔案和包裝函式類別,用於與服務通訊。進階延伸功能預設為啟用。如要啟用基本擴充功能,請將
ExtensionsVersionImpl#isAdvancedExtenderImplemented
變更為回傳false
。extensions_service
:Extensions Service 的範例實作。請在此處新增實作內容。在服務中實作的介面類似於Extensions-Interface
。舉例來說,實作IAdvancedExtenderImpl.Stub
會執行與AdvancedExtenderImpl
相同的作業。需要ImageWrapper
和TotalCaptureResultWrapper
,才能將Image
和TotalCaptureResult
設為可封裝。
在裝置上設定供應商程式庫
OEM 供應商程式庫並未內建於應用程式中,而是由 Camera2/X 在執行階段從裝置載入。在 CameraX 中,<uses-library>
標記宣告了 androidx.camera.extensions.impl
程式庫 (在 camera-extensions
程式庫的 AndroidManifest.xml
檔案中定義的) 是 CameraX 的依附元件,必須在執行階段載入。在 Camera2 中,架構會載入擴充功能服務,而此服務也會宣告 <uses-library>
在執行階段載入相同的 androidx.camera.extensions.impl
程式庫。
這可讓使用擴充功能的第三方應用程式自動載入原始設備製造商 (OEM) 供應商程式庫。OEM 程式庫會標示為選用,因此應用程式可以在沒有該程式庫的裝置上執行。只要裝置製造商將 OEM 程式庫放在裝置上,讓應用程式可以偵測到,當應用程式嘗試使用相機擴充功能時,Camera2/X 就會自動處理這項行為。
如要在裝置上設定 OEM 程式庫,請按照下列步驟操作:
- 使用下列格式新增權限檔案 (
<uses-library>
標記需要此檔案):/etc/permissions/ANY_FILENAME.xml
。例如:/etc/permissions/camera_extensions.xml
。這個目錄中的檔案會將<uses-library>
中命名的程式庫對應至裝置上的實際檔案路徑。 請參考下方範例,在檔案中加入必要資訊。
name
必須是androidx.camera.extensions.impl
,因為是 CameraX 搜尋的程式庫。file
是包含擴充功能實作內容的檔案絕對路徑 (例如/system/framework/androidx.camera.extensions.impl.jar
)。
<?xml version="1.0" encoding="utf-8"?> <permissions> <library name="androidx.camera.extensions.impl" file="OEM_IMPLEMENTED_JAR" /> </permissions>
在 Android 12 以上版本中,支援 CameraX 擴充功能的裝置必須將 ro.camerax.extensions.enabled
屬性設為 true
,才能查詢裝置是否支援擴充功能。如要這麼做,請在裝置製造檔案中加入下列一行:
PRODUCT_VENDOR_PROPERTIES += \
ro.camerax.extensions.enabled=true \
驗證
如要在開發階段測試 OEM 供應商程式庫的導入方式,請使用 androidx-main/camera/integration-tests/extensionstestapp/
中的範例應用程式,該應用程式會透過各種供應商擴充功能執行。
完成導入後,請使用相機擴充功能驗證工具執行自動化和手動測試,驗證供應商程式庫是否正確導入。
擴充場景模式與相機擴充功能
針對 Bokeh 擴充功能,除了使用相機擴充功能外,您還可以使用擴充場景模式來公開該擴充功能,這項模式可透過 CONTROL_EXTENDED_SCENE_MODE
鍵啟用。如要進一步瞭解實作方式,請參閱「相機散景效果」。
與相機 2 應用程式的相機擴充功能相比,擴充場景模式的限制較少。舉例來說,您可以在支援彈性串流組合和擷取要求參數的一般 CameraCaptureSession
執行個體中啟用擴充場景模式。相較之下,相機擴充功能只支援固定的串流類型,且對擷取要求參數的支援有限。
擴充場景模式的缺點是,您只能在相機 HAL 中實作這項模式,也就是說,您必須驗證這項模式是否可在應用程式開發人員可用的所有直角控制項中運作。
建議您同時使用延伸場景模式和相機擴充功能公開散景,因為應用程式可能偏好使用特定 API 啟用散景。我們建議您先使用擴充場景模式,因為這是應用程式啟用 bokeh 擴充功能最具彈性的做法。然後,您可以根據延伸場景模式實作相機擴充功能介面。如果在相機 HAL 中實作散景效果很困難,例如因為需要在應用程式層級執行後置處理器來處理圖片,建議您使用相機擴充功能介面實作散景效果擴充功能。
常見問題 (FAQ)
API 級別是否有任何限制?
可以。這取決於 OEM 供應商程式庫實作項目所需的 Android API 功能組合。舉例來說,ExtenderStateListener.onPresetSession()
會使用 SessionConfiguration.setSessionParameters()
呼叫來設定一組基準代碼。這個呼叫僅適用於 API 級別 28 以上版本。如需特定介面方法的詳細資訊,請參閱 API 參考資料說明文件。