デバイス メーカーは、OEM ベンダー ライブラリが提供する Camera Extensions インターフェイスを介して、ボケ、ナイト モード、HDR などの拡張機能をサード パーティの開発者に公開できます。開発者は、 Camera2 Extensions APIとCameraX Extensions APIを使用して、OEM ベンダー ライブラリに実装されている拡張機能にアクセスできます。
サポートされている拡張機能のリストについては、Camera2 と CameraX で同じです。CameraX Extensions APIを参照してください。拡張機能を追加する場合は、 Issue Trackerでバグを報告してください。
このページでは、デバイスで OEM ベンダー ライブラリを実装して有効にする方法について説明します。
建築
次の図は、Camera Extensions インターフェイスまたはextensions-interface
のアーキテクチャを示しています。
図 1. Camera Extensions のアーキテクチャ図
図に示すように、カメラ エクステンションをサポートするには、OEM ベンダー ライブラリによって提供されるextensions-interface
を実装する必要があります。 OEM ベンダー ライブラリは、 CameraX Extensions APIとCamera2 Extensions API の 2 つの API を有効にします。これらは、それぞれ CameraX アプリと Camera2 アプリで使用され、ベンダー拡張機能にアクセスします。
OEM ベンダー ライブラリを実装する
OEM ベンダー ライブラリを実装するには、 camera-extensions-stub
ファイルをシステム ライブラリ プロジェクトにコピーします。これらのファイルは、Camera Extensions インターフェイスを定義します。
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
Night 拡張クラス (Night 拡張がサポートされている場合は実装)
-
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 拡張クラス (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 クラスをインスタンス化します。
拡張機能の Extender クラスをインスタンス化します。エクステンダーには、ベーシック エクステンダーとアドバンスト エクステンダーの 2 種類があります。すべての拡張機能に対して 1 つのエクステンダー タイプを実装する必要があります。詳細については、 Basic Extender と Advanced Extender の比較を参照してください。
Camera2/X はインスタンスを作成して Extender クラスと対話し、情報を取得して拡張機能を有効にします。特定の拡張機能について、Camera2/X は Extender クラスを複数回インスタンス化できます。そのため、コンストラクターまたは
init()
呼び出しで手間のかかる初期化を行わないでください。 Basic Extender でonInit()
が呼び出されたとき、または Advanced Extender でinitSession()
が呼び出されたときなど、カメラ セッションが開始されようとしているときにのみ、重労働を行います。Night 拡張機能の場合、次の Extender クラスが Basic Extender タイプ用にインスタンス化されます。
-
NightImageCaptureExtenderImpl.java
-
NightPreviewExtenderImpl.java
Advanced Extender タイプの場合:
-
NightAdvancedExtenderImpl.java
-
拡張機能の可用性を確認します。
拡張機能を有効にする前に、
isExtensionAvailable()
は、Extender インスタンスを介して、指定されたカメラ ID で拡張機能が利用可能かどうかを確認します。カメラ情報を使用してエクステンダーを初期化します。
Camera2/X は Extender インスタンスで
init()
を呼び出し、カメラ ID とCameraCharacteristics
を渡します。クエリ情報:
Extender クラスを呼び出して、サポートされている解像度などの情報を取得し、推定レイテンシを取得し、拡張機能を有効にする準備として Extender から要求キーを取得します。
Extender で拡張機能を有効にします。
Extender クラスは、クラスを有効にするために必要なすべてのインターフェイスを提供します。キャプチャ リクエスト パラメータの挿入やポスト プロセッサの有効化など、OEM 実装を Camera2 パイプラインにフックするメカニズムを提供します。
Advanced Extender タイプの場合、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 ライブラリによって報告されたバージョンを使用して、拡張機能を有効にできるかどうか、およびどの機能を呼び出す必要があるかを判断します。
メジャー バージョンの互換性
拡張インターフェイスのメジャー バージョンが 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 ライブラリに通知します。
Camera2/X は、OEM ベンダー ライブラリがOnExtensionsInitializedCallback.onSuccess()
を呼び出して初期化の完了を通知するまで、(バージョン チェックを除いて) OEM ライブラリへの他の呼び出しを行いません。
extensions-interface
1.1.0 の時点でInitializerImpl
を実装する必要があります。 OEM ベンダー ライブラリがextensions-interface
実装している場合、Camera2/X はライブラリの初期化手順をスキップします。
Basic Extender と Advanced Extender の比較
extensions-interface
の実装には、Basic Extender と Advanced Extender の 2 種類があります。 Advanced Extender は、 extensions-interface
1.2.0 以降でサポートされています。
カメラ HAL で画像を処理する拡張機能、または YUV ストリームを処理できるポスト プロセッサを使用する拡張機能の Basic Extender を実装します。
Camera2 ストリーム構成をカスタマイズし、必要に応じてキャプチャ要求を送信する必要がある拡張機能用に Advanced Extender を実装します。
比較については、次の表を参照してください。
ベーシックエクステンダー | 高度なエクステンダー | |
---|---|---|
ストリーム構成 | 修理済み プレビュー: PRIVATE またはYUV_420_888 (プロセッサが存在する場合)静止キャプチャ: JPEG またはYUV_420_888 (プロセッサが存在する場合) | OEMによるカスタマイズ可能。 |
キャプチャリクエストの送信 | Camera2/X のみがキャプチャ リクエストを送信できます。これらのリクエストにパラメータを設定できます。プロセッサが画像キャプチャ用に提供されている場合、Camera2/X は複数のキャプチャ要求を送信し、すべての画像とキャプチャ結果をプロセッサに送信できます。 | camera2 キャプチャ リクエストを実行し、結果とイメージを取得するために、 RequestProcessorImpl インスタンスが提供されます。 Camera2/X は、 |
カメラ パイプラインのフック |
|
|
に適し | カメラ HAL または YUV 画像を処理するプロセッサに実装された拡張機能。 |
|
サポートされている API バージョン | Camera2 拡張機能: Android 13 以降 CameraX 拡張機能: camera-extensions 1.1.0 以降 | Camera2 拡張機能: Android 12L 以降 CameraX 拡張機能: camera-extensions 1.2.0-alpha03 以降 |
アプリの流れ
次の表は、3 種類のアプリ フローと、対応する 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 bindToLifecycle(lifecycleOwner, cameraSelector, preview, ...) |
ベーシックエクステンダー
Basic Extender インターフェイスは、カメラ パイプラインのいくつかの場所へのフックを提供します。各拡張機能の種類には、OEM が実装する必要がある対応するエクステンダー クラスがあります。
次の表に、OEMS が拡張機能ごとに実装する必要があるエクステンダー クラスを示します。
実装する拡張クラス | |
---|---|
夜 | NightPreviewExtenderImpl.java |
HDR | HdrPreviewExtenderImpl.java
|
自動 | AutoPreviewExtenderImpl.java
|
ボケ | BokehPreviewExtenderImpl.java
|
顔レタッチ | BeautyPreviewExtenderImpl.java
|
次の例では、 PreviewExtenderImpl
とImageCaptureExtenderImpl
をプレースホルダーとして使用しています。これらを、実装している実際のファイルの名前に置き換えます。
Basic Extender には、次の機能があります。
-
CameraCaptureSession
(onPresetSession
) を構成するときにセッション パラメーターを挿入します。 - キャプチャ セッションの開始イベントと終了イベントを通知し、返されたパラメーター (
onEnableSession
、onDisableSession
) を使用して HAL に通知する単一の要求を送信します。 - リクエストのキャプチャ パラメータを挿入します (
PreviewExtenderImpl.getCaptureStage
、ImageCaptureExtenderImpl.getCaptureStages
)。 -
YUV_420_888
ストリームを処理できるプレビューおよび静止キャプチャ用のプロセッサを追加します。
Camera2/X がextensions-interface
を呼び出して、上記の 3 つのアプリ フローを実現する方法を見てみましょう。
アプリ フロー 1: 拡張機能の可用性を確認する
図 3. Basic Extender でのアプリ フロー 1
このフローでは、Camera2/X はinit()
を呼び出さずに、 PreviewExtenderImpl
とImageCaptureExtenderImpl
の両方のisExtensionAvailable()
メソッドを直接呼び出します。拡張機能を有効にするには、両方の Extender クラスがtrue
を返す必要があります。
多くの場合、これは、拡張機能を有効にする前に、特定の拡張タイプが特定のカメラ ID でサポートされているかどうかをアプリが確認する最初のステップです。これは、一部の拡張機能が特定のカメラ ID でのみサポートされているためです。
アプリ フロー 2: クエリ情報
図 4. Basic Extender でのアプリ フロー 2
拡張機能が利用可能かどうかを判断した後、アプリは拡張機能を有効にする前に次の情報を照会する必要があります。
まだキャプチャ レイテンシの範囲:
ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
は、現在のシナリオで拡張機能を有効にすることが適切かどうかを評価するために、アプリのキャプチャ レイテンシの範囲を返します。プレビュー サーフェスとキャプチャ サーフェスでサポートされているサイズ:
ImageCaptureExtenderImpl.getSupportedResolutions
とPreviewExtenderImpl.getSupportedResolutions
は、イメージ フォーマットのリストと、サーフェスのフォーマットとサイズでサポートされているサイズを返します。サポートされているリクエスト キーと結果キー: Camera2/X は、次のメソッドを呼び出して、サポートされているキャプチャ リクエスト キーと結果キーを実装から取得します。
-
ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
-
ImageCaptureExtenderImpl.getAvailableCapturetResultKeys
-
Camera2/X は、詳細情報を照会する前に、これらの Extender クラスで最初にinit()
を常に呼び出します。
アプリ フロー 3: 拡張機能を有効にしてプレビュー/静止画キャプチャ (HAL 実装)
図 5. Basic Extender でのアプリ フロー 3
上の図は、プレビューを有効にして、プロセッサなしで拡張機能を使用してキャプチャするメイン フローを示しています。これは、カメラ HAL が拡張機能を処理することを意味します。
このフローでは、Camera2/X は最初にinit()
を呼び出し、次にonInit
を呼び出します。これにより、カメラ セッションが指定された拡張子で開始されようとしていることを通知します。 onInit()
で手間のかかる初期化を行うことができます。
CameraCaptureSession
を設定するとき、Camera2/X はonPresetSession
を呼び出してセッション パラメータを取得します。キャプチャ セッションが正常に構成された後、Camera2/X は、キャプチャ パラメータを含むCaptureStageImpl
インスタンスを返すonEnableSession
を呼び出します。 Camera2/X は、HAL に通知するために、これらのキャプチャ パラメータを含む 1 つのリクエストをすぐに送信します。同様に、キャプチャ セッションが閉じられる前に、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
は、RequestUpdateProcessorImpl
インスタンスを処理するTotalCaptureResult
インスタンスを返し、CaptureStageImpl
インスタンスを返して繰り返し要求を更新する必要があります。PreviewExtenderImpl.getCaptureStage()
も処理の結果を反映し、最新のCaptureStageImpl
を返す必要があります。PROCESSOR_TYPE_IMAGE_PROCESSOR
:このタイプを使用すると、プロセッサを実装してYUV_420_888
画像を処理し、出力をPRIVATE
サーフェスに書き込むことができます。PreviewExtenderImpl.getProcessor
でPreviewImageProcessorImpl
インスタンスを実装して返す必要があります。プロセッサは、YUV_420_888
入力画像の処理を担当します。出力をプレビューのPRIVATE
形式に書き込む必要があります。 Camera2/X は、PRIVATE
の代わりにYUV_420_888
サーフェスを使用して、プレビュー用にCameraCaptureSession
を構成します。フローについては、次の図を参照してください。
図 6. PreviewImageProcessorImpl
を使用したプレビュー フロー
PreviewImageProcessorImpl
インターフェイスはProcessImpl
を拡張し、次の 3 つの重要なメソッドを持ちます。
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
CaptureProcessorImpl.onImageFormatUpdate()
とYUV_420_888
。 -
CaptureProcessorImpl.onResolutionUpdate()
と入力画像サイズ。 - 出力
YUV_420_888
サーフェスを持つ CaptureProcessorImpl.onOutputSurfaceCaptureProcessorImpl.onOutputSurface()
。
- CaptureProcessorImpl.onImageFormatUpdate
ImageCaptureExtenderImpl.getCaptureStages
はCaptureStageImpl
のリストを返します。ここで、各要素は、Camera2/X によって送信されるキャプチャ パラメータを持つCaptureRequest
インスタンスにマップされます。たとえば、3 つのCaptureStageImpl
インスタンスのリストを返す場合、Camera2/X は、captureBurst
API を使用して、対応するキャプチャ パラメータを含む 3 つのキャプチャ リクエストを送信します。受信した画像と
TotalCaptureResult
インスタンスはまとめてバンドルされ、処理のためにCaptureProcessorImpl
に送信されます。CaptureProcessorImpl
は、結果の Image (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 以降では、2 番目の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);
}
ズーム、タップしてフォーカス、フラッシュ、露出補正などの一般的なカメラ操作については、キャプチャ要求とキャプチャ結果の両方で次のキーをサポートすることをお勧めします。
- ズーム:
-
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
-
- 閃光:
-
CaptureRequest#CONTROL_AE_MODE
-
CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
-
CaptureRequest#FLASH_MODE
-
- 露出補正:
-
CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
-
1.2.0 以前のバージョンを実装する Basic Extender の場合、CameraX Extensions API は上記のすべてのキーを明示的にサポートします。 extensions-interface
1.3.0 の場合、CameraX と Camera2 の両方が返されたリストを尊重し、それに含まれるキーのみをサポートします。たとえば、1.3.0 の実装でCaptureRequest#CONTROL_ZOOM_RATIO
とCaptureRequest#SCALER_CROP_REGION
のみを返すことにした場合、それはアプリでズームのみがサポートされ、タップしてフォーカス、フラッシュ、および露出補正が許可されていないことを意味します。
高度なエクステンダー
Advanced Extender は、Camera2 API に基づくベンダー実装の一種です。このエクステンダー タイプは、 extensions-interface
1.2.0 で追加されました。デバイスの製造元によっては、拡張機能がアプリ レイヤーに実装される場合があります。これは、次の要因に依存します。
カスタム ストリーム構成: RAW ストリームなどのカスタム ストリームを構成するか、異なる物理カメラ ID に対して複数のストリームを用意します。
Camera2 リクエストを送信する機能:以前のリクエストの結果に基づいてパラメーターを使用してキャプチャ リクエストを送信できる複雑な対話ロジックをサポートします。
Advanced Extender はラッパーまたは中間レイヤーを提供するため、ストリーム構成をカスタマイズして、オンデマンドでキャプチャー要求を送信できます。
実装するファイル
Advanced Extender 実装に切り替えるには、 ExtensionVersionImpl
のisAdvancedExtenderImplemented()
メソッドがtrue
を返す必要があります。拡張機能の種類ごとに、OEM は対応するエクステンダー クラスを実装する必要があります。 Advanced Extender の実装ファイルは、高度なパッケージに含まれています。
実装する拡張クラス | |
---|---|
夜 | advanced/NightAdvancedExtenderImpl.java |
HDR | advanced/HdrAdvancedExtenderImpl.java |
自動 | advanced/AutoAdvancedExtenderImpl.java |
ボケ | advanced/BokehAdvancedExtenderImpl.java |
顔レタッチ | advanced/BeautyAdvancedExtenderImpl.java |
次の例では、 AdvancedExtenderImpl
をプレースホルダーとして使用しています。実装している拡張機能のエクステンダー ファイルの名前に置き換えます。
Camera2/X がextensions-interface
を呼び出して 3 つのアプリ フローを実現する方法を見てみましょう。
アプリ フロー 1: 拡張機能の可用性を確認する
図 8. Advanced Extender でのアプリ フロー 1
最初に、アプリは指定された拡張機能がサポートされているかどうかを確認します。
アプリ フロー 2: クエリ情報
図 9. Advanced Extender でのアプリ フロー 2
AdvancedExtenderImpl.init()
を呼び出した後、アプリはAdvancedExtenderImpl
に関する次の情報を照会できます。
推定静止キャプチャ レイテンシ:
AdvancedExtenderImpl.getEstimatedCaptureLatencyRange()
は、現在のシナリオで拡張機能を有効にすることが適切かどうかを評価するために、アプリのキャプチャ レイテンシの範囲を返します。プレビューと静止キャプチャでサポートされている解像度:
AdvancedExtenderImpl.getSupportedPreviewOutputResolutions()
は、プレビュー サーフェスの形式とサイズでサポートされているサイズ リストへの画像形式のマップを返します。 OEM は、少なくともPRIVATE
形式をサポートする必要があります。AdvancedExtenderImpl.getSupportedCaptureOutputResolutions()
は、静止キャプチャ サーフェスのサポートされている形式とサイズを返します。 OEM は、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. Advanced Extender でのアプリ フロー 3
上の図は、プレビューを開始し、アドバンスト エクステンダー タイプのスチル キャプチャを開始するためのメイン フローを示しています。各ステップを見ていきましょう。
SessionProcessorImpl
インスタンスAdvanced Extender のコア実装は
SessionProcessorImpl
にあります。これは、カスタマイズされたセッション構成を提供し、キャプチャ要求を送信してプレビューを開始し、要求をキャプチャします。AdvancedExtenderImpl.createSessionProcessor()
が呼び出されて、SessionProcessorImpl
インスタンスが返されます。initSession
SessionProcessorImpl.initSession()
は、拡張機能のセッションを初期化します。ここでリソースを割り当て、CameraCaptureSession
を準備するためのセッション構成を返します。入力パラメーターについては、Camera2/X は、プレビュー、静止キャプチャ、およびオプションの YUV 画像分析の出力サーフェス構成を指定します。この出力サーフェス構成 (
OutputSurfaceImpl
) には、AdvancedExtenderImpl
の次のメソッドによって取得されるサーフェス、サイズ、および画像形式が含まれています。-
getSupportedPreviewOutputResolutions()
-
getSupportedCaptureOutputResolutions()
-
getSupportedYuvAnalysisResolutions()
Camera2OutputConfigImpl
インスタンスのリストと、CameraCaptureSession
の構成に使用されるセッション パラメータで構成されるCamera2SessionConfigImpl
インスタンスを返す必要があります。 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
が開始され、Camera フレームワークが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
インスタンスは無効になります。- ターゲット サーフェスは、
プレビューを開始して写真を撮る
Advanced Extender 実装では、
RequestProcessorImpl
インターフェースを介してキャプチャー要求を送信できます。 Camera2/X は、それぞれ SessionProcessorImplSessionProcessorImpl#startRepeating
とSessionProcessorImpl#startCapture
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()
で通知されなかったキャプチャ リクエスト キーは無視できます。startTrigger()
はextensions-interface
1.3.0 以降でサポートされています。これにより、アプリは拡張機能を使用してタップしてフォーカスとフラッシュを実装できます。掃除
キャプチャ セッションを終了すると、
CameraCaptureSession
を閉じる前にSessionProcessorImpl.onCaptureSessionEnd()
が呼び出されます。キャプチャ セッションが閉じた後、deInitSession()
はクリーンアップを実行します。
プレビュー、静止画キャプチャ、画像解析をサポート
プレビューと静止キャプチャの両方のユース ケースに拡張機能を適用する必要があります。ただし、待ち時間が長すぎてプレビューをスムーズに表示できない場合は、拡張機能を静止キャプチャにのみ適用できます。
Basic Extender タイプの場合、プレビュー用に拡張機能を有効にするかどうかに関係なく、特定の拡張機能に対してImageCaptureExtenderImpl
とPreviewExtenderImpl
の両方を実装する必要があります。 Often, an app also uses a YUV stream to analyze the image content such as finding QR codes or text. To better support this use case , you should support the stream combination of preview, still capture, and a YUV_420_888
stream for configuring CameraCaptureSession
. This means that if you implement a processor, then you have to support the stream combination of three YUV_420_888
streams.
For Advanced Extender, Camera2/X passes three output surfaces to the SessionProcessorImpl.initSession()
call. These output surfaces are for preview , still capture, and image analysis, respectively. You must ensure that preview and still capture output surfaces show the valid output. However, for the image analysis output surface, ensure it's working only when it's non-null. If your implementation can't support the image analysis stream, you can return an empty list in AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions()
. This ensures the image analysis output surface is always null in SessionProcessorImpl.initSession()
.
Support video capture
The current Camera Extension architecture supports only the preview and still capture use cases. We don't support enabling the extension on the MediaCodec
or MediaRecorder
surfaces for recording the video. However, it's possible for apps to record the preview output.
Supporting MediaCodec
and MediaRecorder
surfaces is under investigation.
Extensions interface version history
The following table shows the Camera Extension interface version history. You should always implement the vendor library with the latest version.
Version | Added features |
---|---|
1.0.0 |
|
1.1.0 |
|
1.2.0 |
|
1.3.0 |
|
Reference implementation
For a reference OEM vendor library implementation, see camera-testlib-extensions
. Note that this implementation performs passthroughs without actually implementing the extensions.
Set up the vendor library on a device
The OEM vendor library isn't built into an app; it's loaded from the device at runtime by Camera2/X. In CameraX, the <uses-library>
tag declares that the androidx.camera.extensions.impl
library, which is defined in the AndroidManifest.xml
file of the camera-extensions
library, is a dependency of CameraX and must be loaded at runtime. In Camera2, the framework loads an extensions service that also declares that the <uses-library>
loads the same androidx.camera.extensions.impl
library at runtime.
This allows third-party apps using extensions to automatically load the OEM vendor library. The OEM library is marked as optional so apps can run on devices that don't have the library on the device. Camera2/X handles this behavior automatically when an app tries to use a camera extension as long as the device manufacturer places the OEM library on the device so that it can be discovered by the app.
To set up the OEM library on a device, do the following:
- Add a permission file, which is required by the
<uses-library>
tag, using the following format:/etc/permissions/ ANY_FILENAME .xml
. For example,/etc/permissions/camera_extensions.xml
. The files in this directory provide a mapping of the library named in<uses-library>
to the actual file path on the device. Use the example below to add the required information to the file.
-
name
must beandroidx.camera.extensions.impl
as that's the library that CameraX searches for. -
file
is the absolute path of the file that contains the extensions implementation (for example,/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>
-
In Android 12 or higher, devices supporting CameraX extensions must have the ro.camerax.extensions.enabled
property set to true
, which allows for querying whether a device supports extensions. To do this, add the following line in the device make file:
PRODUCT_VENDOR_PROPERTIES += \
ro.camerax.extensions.enabled=true \
Validation
To test your implementation of the OEM vendor library during the development stage, use the example app at androidx-main/camera/integration-tests/extensionstestapp/
, which runs through various vendor extensions.
After you complete your implementation, use the Camera Extensions Validation Tool to run automated and manual tests to verify that the vendor library is implemented correctly.
Extended scene mode versus Camera Extensions
For the bokeh extension, in addition to exposing it using Camera Extensions, you can expose the extension using the extended scene mode, which is enabled through the CONTROL_EXTENDED_SCENE_MODE
key. For more implementation details, see Camera Bokeh .
Extended scene mode has fewer restrictions compared to Camera Extensions for camera2 apps. For example, you can enable extended scene mode in a regular CameraCaptureSession
instance that supports flexible stream combinations and capture request parameters. In contrast, camera extensions support only a fixed set of stream types and have limited support for capture request parameters.
A downside of extended scene mode is that you can only implement it in the camera HAL, which means that it must be verified to work across all orthogonal controls available to app developers.
We recommend exposing bokeh using both the extended scene mode and Camera Extensions because apps might prefer to use a particular API to enable bokeh. We recommend first using the extended scene mode because this is the most flexible way for apps to enable the bokeh extension. Then you can implement the camera extensions interface based on the extended scene mode. If implementing bokeh in the camera HAL is difficult, for example, because it requires a post processor running in the app layer to process images, we recommend implementing the bokeh extension using the Camera Extensions interface.
Frequently asked questions (FAQs)
Are there any restrictions on API levels?
Yes. This depends on the Android API feature set that's required by the OEM vendor library implementation. For example, ExtenderStateListener.onPresetSession()
uses the SessionConfiguration.setSessionParameters()
call to set a baseline set of tags. This call is available only on API level 28 and higher. For details on specific interface methods, see the API reference documentation .