カメラ拡張機能

デバイス メーカーは、OEM ベンダー ライブラリによって提供されるカメラ拡張機能インターフェースを介して、ボケ、夜間モード、HDR などの拡張機能をサードパーティ デベロッパーに公開できます。デベロッパーは、Camera2 Extensions APICameraX Extensions API を使用して、OEM ベンダー ライブラリに実装されている拡張機能にアクセスできます。

Camera2 と CameraX で共通してサポートされる拡張機能のリストについては、CameraX Extensions API をご覧ください。拡張機能を追加する場合は、Issue Tracker でバグを報告してください。

このページでは、デバイスに OEM ベンダー ライブラリを実装して有効化する方法について説明します。

アーキテクチャ

次の図は、カメラ拡張機能インターフェース(extensions-interface)のアーキテクチャを示しています。アーキテクチャ

図 1. カメラ拡張機能アーキテクチャの図

図に示されているように、カメラ拡張機能をサポートするには、OEM ベンダー ライブラリによって提供される extensions-interface を実装する必要があります。OEM ベンダー ライブラリを実装すると、CameraX Extensions APICamera2 Extensions API という 2 つの API が有効化されます。これらの 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

ボケ エクステンダー クラス(ボケ拡張機能がサポートされている場合に実装)

  • 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

顔写真加工エクステンダー クラス(顔写真加工拡張機能がサポートされている場合に実装)

  • BeautyImageCaptureExtenderImpl.java
  • BeautyPreviewExtenderImpl.java
  • advanced/BeautyAdvancedExtenderImpl.java

ユーティリティ(任意、削除可能)

  • advanced/Camera2OutputConfigImplBuilder.java
  • advanced/Camera2SessionConfigImplBuilder.java

すべての拡張機能について実装を用意する必要はありません。拡張機能を実装しない場合は、isExtensionAvailable() を設定して false を返すか、対応するエクステンダー クラスを削除します。Camera2 Extensions API と CameraX Extensions API は、その拡張機能が利用不可であることをアプリに報告します。

それでは、Camera2 Extensions API と CameraX Extensions API がベンダー ライブラリを操作して拡張機能を有効化する仕組みを見てみましょう。次の図は、夜間モード拡張機能を使用するエンドツーエンドのフローの例を示しています。

メインフロー

図 2. 夜間モード拡張機能の実装

  1. バージョンの確認:

    Camera2/X は、ExtensionVersionImpl.checkApiVersion() を呼び出して、OEM が実装した extensions-interface のバージョンと Camera2/X のサポートされているバージョンに互換性があるかどうかを確認します。

  2. ベンダー ライブラリを初期化する:

    InitializerImpl には、ベンダー ライブラリを初期化する init() メソッドがあります。Camera2/X は、エクステンダー クラスにアクセスする前に初期化を完了します。

  3. エクステンダー クラスをインスタンス化する:

    拡張機能のエクステンダー クラスをインスタンス化します。エクステンダーには、ベーシック エクステンダーとアドバンスト エクステンダーの 2 つのタイプがあります。すべての拡張機能に対して、どちらかのエクステンダー タイプを実装する必要があります。詳しくは、ベーシック エクステンダーとアドバンスト エクステンダーをご覧ください。

    Camera2/X は、エクステンダー クラスをインスタンス化して操作し、情報を取得して拡張機能を有効化します。特定の拡張機能について、Camera2/X はエクステンダー クラスを複数回インスタンス化できます。したがって、コンストラクタまたは init() 呼び出しで負荷の高い初期化を行わないでください。負荷の高い作業は、カメラ セッションが開始されるときにだけ行ってください。たとえば、ベーシック エクステンダーで onInit() が呼び出されときや、アドバンスト エクステンダーで initSession() が呼び出されたときです。

    夜間モード拡張機能の場合、ベーシック エクステンダー タイプでは、以下のエクステンダー クラスがインスタンス化されます。

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    アドバンスト エクステンダー タイプでは、以下のエクステンダー クラスがインスタンス化されます。

    • NightAdvancedExtenderImpl.java
  4. 拡張機能の利用可能性を確認する:

    isExtensionAvailable() は、拡張機能を有効化する前に、エクステンダー インスタンスを介して、指定されたカメラ ID で拡張機能が利用可能かどうかを確認します。

  5. カメラ情報でエクステンダーを初期化する:

    Camera2/X は、エクステンダー インスタンスで init() を呼び出し、カメラ ID と CameraCharacteristics を渡します。

  6. 情報をクエリする:

    拡張機能を有効化する準備として、エクステンダー クラスを呼び出し、サポートされている解像度、静止画撮影レイテンシの推定値、キャプチャ リクエスト キーなどの情報をエクステンダーから取得します。

  7. エクステンダーで拡張機能を有効化する:

    エクステンダー クラスは、クラスの有効化に必要なインターフェースをすべて備えています。それにより、OEM の実装を Camera2 パイプラインにフックするメカニズム(キャプチャ リクエストのパラメータの注入やポスト プロセッサの有効化など)が提供されます。

    アドバンスト エクステンダー タイプの場合、Camera2/X は SessionProcessorImpl を操作して拡張機能を有効化します。Camera2/X は、エクステンダーで 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 ライブラリに通知します。

Camera2/X は、OEM ベンダー ライブラリが OnExtensionsInitializedCallback.onSuccess() を呼び出して初期化の完了を通知するまで、OEM ライブラリに対するその他の(バージョン チェック以外の)呼び出しは行いません。

extensions-interface 1.1.0 では、InitializerImpl を実装する必要があります。OEM ベンダー ライブラリが extensions-interface 1.0.0 を実装している場合、Camera2/X はライブラリを初期化するステップをスキップします。

ベーシック エクステンダーとアドバンスト エクステンダー

extensions-interface 実装には、ベーシック エクステンダーとアドバンスト エクステンダーの 2 つのタイプがあります。アドバンスト エクステンダーは、extensions-interface 1.2.0 以降でサポートされます。

カメラ HAL で画像を処理する拡張機能、または YUV ストリームを処理できるポスト プロセッサを使用する拡張機能については、ベーシック エクステンダーを実装します。

必要に応じて Camera2 ストリーム構成をカスタマイズしてキャプチャ リクエストを送信する必要がある拡張機能については、アドバンスト エクステンダーを実装します。

これらの比較については、次の表をご覧ください。

ベーシック エクステンダー アドバンスト エクステンダー
ストリーム構成 修正済み
プレビュー: PRIVATE または YUV_420_888(プロセッサが存在する場合)
静止画撮影: JPEG または YUV_420_888(プロセッサが存在する場合)
OEM がカスタマイズできます。
キャプチャ リクエストの送信 キャプチャ リクエストを送信できるのは Camera2/X のみです。リクエストにパラメータを設定できます。画像キャプチャ用のプロセッサが提供されている場合、Camera2/X は複数のキャプチャ リクエストを送信して、すべての画像とキャプチャ結果をプロセッサに送信できます。 Camera2 キャプチャ リクエストを実行して結果と画像を取得するための RequestProcessorImpl インスタンスが用意されています。

Camera2/X は、SessionProcessorImplstartRepeatingstartCapture を呼び出すことにより、プレビューの反復リクエストの開始と静止画撮影シーケンスの開始をそれぞれ OEM に通知します。

カメラ パイプラインのフック
  • onPresetSession は、セッション パラメータを提供します。
  • onEnableSession は、CameraCaptureSession が構成された直後に単一のリクエストを送信します。
  • onDisableSession は、CameraCaptureSession が閉じる前に単一のリクエストを送信します。
  • initSession は、キャプチャ セッションを作成するためのカスタマイズされた Camera2 セッション構成を初期化して返します。
  • onCaptureSessionStart は、CameraCaptureSession が構成された直後に呼び出されます。
  • onCaptureSessionEnd は、CameraCaptureSession が閉じる前に呼び出されます。
適しているケース: カメラ HAL、または YUV 画像を処理するプロセッサに実装された拡張機能。
  • Camera2 ベースの拡張機能用の実装があります。
  • RAW ストリームなど、カスタマイズされたストリーム構成が必要です。
  • インタラクティブなキャプチャ シーケンスが必要です。
サポートされている 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 を提供しますが、OEM は下記のフローをサポートするベンダー ライブラリを適切に実装する必要があります。詳しくは、この後のセクションで説明します。

Camera2 拡張機能 CameraX 拡張機能
拡張機能の利用可能性をクエリする CameraExtensionCharacteristics .getSupportedExtensions ExtensionsManager. isExtensionAvailable
情報をクエリする CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

ライブラリ内の残りの情報は CameraX が処理します。

拡張機能を有効化してプレビューと静止画撮影を行う CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

bindToLifecycle(lifecycleOwner, cameraSelector, preview, ...)

ベーシック エクステンダー

ベーシック エクステンダー インターフェースは、カメラ パイプライン内のいくつかの場所へのフックを提供します。拡張機能タイプごとに、OEM が実装する必要があるエクステンダー クラスがあります。

次の表に、拡張機能ごとに OEM が実装する必要があるエクステンダー クラスを示します。

実装するエクステンダー クラス
夜間モード NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

自動 AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

ボケ BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

顔写真加工 BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

以下の例では、プレースホルダとして PreviewExtenderImplImageCaptureExtenderImpl を使用しています。これらは、実装する実際のファイルの名前に置き換えてください。

ベーシック エクステンダーは以下の機能を備えています。

  • CameraCaptureSessiononPresetSession)を構成する際にセッション パラメータを注入する。
  • キャプチャ セッションの開始イベントと終了イベントを OEM に通知する。単一のリクエストを送信して、返されたパラメータ(onEnableSessiononDisableSession)を HAL に通知する。
  • リクエストのキャプチャ パラメータ(PreviewExtenderImpl.getCaptureStageImageCaptureExtenderImpl.getCaptureStages)を注入する。
  • YUV_420_888 ストリームを処理できるプレビューと静止画撮影用のプロセッサを追加する。

Camera2/X が extensions-interface を呼び出して、上記の 3 つのアプリフローを実現する仕組みを見てみましょう。

アプリフロー 1: 拡張機能の利用可能性を確認する

BasicExtenderAppFlow1

図 3. ベーシック エクステンダーのアプリフロー 1

このフローでは、Camera2/X は init() を呼び出さずに、PreviewExtenderImplImageCaptureExtenderImpl の両方の isExtensionAvailable() メソッドを直接呼び出します。拡張機能を有効化するには、両方のエクステンダー クラスで true を返す必要があります。

これは、多くの場合、拡張機能を有効化する前に、特定の拡張機能タイプが特定のカメラ ID でサポートされているかどうかをアプリが確認するための最初のステップです。なぜなら、一部の拡張機能は特定のカメラ ID でのみサポートされているからです。

アプリフロー 2: 情報をクエリする

BasicExtenderAppFlow2

図 4. ベーシック エクステンダーのアプリフロー 2

拡張機能が利用可能かどうかを確認した後、アプリは拡張機能を有効化する前に以下の情報をクエリする必要があります。

  • 静止画撮影レイテンシの範囲: ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange は、現在のシナリオで拡張機能の有効化が妥当かどうかをアプリが評価するためのキャプチャ レイテンシの範囲を返します。

  • プレビューおよびキャプチャ サーフェスのサポートされているサイズ: ImageCaptureExtenderImpl.getSupportedResolutionsPreviewExtenderImpl.getSupportedResolutions は、サーフェス形式とサイズでサポートされている画像形式とサイズのリストを返します。

  • サポートされているリクエストキーと結果キー: Camera2/X は、以下のメソッドを呼び出して、サポートされているキャプチャ リクエスト キーと結果キーを実装から取得します。

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

Camera2/X は、さらに情報をクエリする前に、必ずこれらのエクステンダー クラスで init() を呼び出します。

アプリフロー 3: 拡張機能を有効化してプレビューと静止画撮影を行う(HAL 実装)

BasicExtenderAppFlow3

図 5. ベーシック エクステンダーのアプリフロー 3

上の図は、プロセッサなしで拡張機能を使用してプレビューと静止画撮影を有効化するメインフローを示しています。これは、カメラ HAL が拡張機能を処理することを意味します。

このフローでは、Camera2/X は最初に init() を呼び出してから onInit を呼び出し、指定された拡張機能でカメラ セッションを開始することを OEM に通知します。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 は、反復リクエストを更新するために、RequestUpdateProcessorImpl インスタンスを返す必要があります。このインスタンスは、TotalCaptureResult インスタンスを処理して CaptureStageImpl インスタンスを返します。また、PreviewExtenderImpl.getCaptureStage() は、処理の結果を反映し、最新の CaptureStageImpl を返す必要があります。

  • PROCESSOR_TYPE_IMAGE_PROCESSOR: このタイプでは、プロセッサを実装し、YUV_420_888 画像を処理して出力を PRIVATE サーフェスに書き込むことができます。

    PreviewExtenderImpl.getProcessorPreviewImageProcessorImpl インスタンスを実装して返す必要があります。プロセッサは YUV_420_888 入力画像を処理します。出力はプレビューの PRIVATE 形式に書き込みます。Camera2/X は、PRIVATE ではなく YUV_420_888 サーフェスを使用して、プレビュー用の CameraCaptureSession を構成します。

    フローについては次の図をご覧ください。

PreviewProcessor

図 6. PreviewImageProcessorImpl を使用したプレビュー フロー

PreviewImageProcessorImpl インターフェースは ProcessImpl の拡張であり、次の 3 つの重要なメソッドを備えています。

  • onOutputSurface(Surface surface, int imageFormat) は、プロセッサ用の出力サーフェスを設定します。PreviewImageProcessorImpl では、imageFormatPixelFormat.RGBA_8888 などのピクセル形式です。

  • onResolutionUpdate(Size size) は、入力画像のサイズを設定します。

  • onImageFormatUpdate(int imageFormat) は、入力画像の画像形式を設定します。現時点では YUV_420_888 のみが使用可能です。

画像キャプチャ プロセッサ

静止画撮影については、ImageCaptureExtenderImpl.getCaptureProcessor を使用して CaptureProcessorImpl インスタンスを返すことにより、プロセッサを実装できます。プロセッサは、キャプチャされた YUV_420_888 画像と TotalCaptureResult インスタンスのリストを処理し、出力を YUV_420_888 サーフェスに書き込みます。

静止画撮影リクエストを送信する前に、プレビューが有効化されて実行されていると想定できます。

次の図のフローをご覧ください。

CaptureProcessor

図 7. CaptureProcessorImpl を使用した静止画撮影フロー

  1. Camera2/X は、静止画撮影については YUV_420_888 形式のサーフェスを使用して、キャプチャ セッションを構成します。Camera2/X は、以下を呼び出して CaptureProcessorImpl を準備します。

    • CaptureProcessorImpl.onImageFormatUpdate()YUV_420_888 を指定)
    • CaptureProcessorImpl.onResolutionUpdate()(入力画像サイズを指定)
    • CaptureProcessorImpl.onOutputSurface()YUV_420_888 出力サーフェスを指定)
  2. ImageCaptureExtenderImpl.getCaptureStagesCaptureStageImpl のリストを返します。このリストの各要素は、Camera2/X によって送信されるキャプチャ パラメータを含む CaptureRequest インスタンスにマッピングされます。たとえば、3 つの CaptureStageImpl インスタンスのリストを返す場合、Camera2/X は、captureBurst API を使用して、対応するキャプチャ パラメータを含む 3 つのキャプチャ リクエストを送信します。

  3. 受信した画像と TotalCaptureResult インスタンスは、バンドルされて処理のために CaptureProcessorImpl に送信されます。

  4. 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 でキャプチャ結果を取得します。この結果は、PreviewImageProcessorImplCaptureProcessorImplprocess() メソッドに渡されます。OEM は、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 以前のバージョンを実装するベーシック エクステンダーの場合、CameraX Extensions API は上記のキーをすべて明示的にサポートします。extensions-interface 1.3.0 の場合、CameraX と Camera2 は両方とも返されるリストを尊重し、リストに含まれるキーのみをサポートします。たとえば、1.3.0 の実装で CaptureRequest#CONTROL_ZOOM_RATIOCaptureRequest#SCALER_CROP_REGION のみを返す場合、アプリではズームのみがサポートされ、タップしてフォーカス、フラッシュ、露出補正は使用できません。

アドバンスト エクステンダー

アドバンスト エクステンダーは、Camera2 API をベースとするベンダー実装のタイプです。このエクステンダー タイプは extensions-interface 1.2.0 で追加されました。デバイス メーカーによっては、拡張機能がアプリレイヤに実装されることがあります。これは以下の要因で決まります。

  • カスタム ストリーム構成: RAW ストリームなどのカスタム ストリームを構成できます。または、物理カメラ ID ごとに複数のストリームを設定できます。

  • Camera2 リクエストを送信する機能: 以前のリクエストの結果に基づいたパラメータでキャプチャ リクエストを送信できる複雑なインタラクション ロジックをサポートします。

アドバンスト エクステンダーは、ラッパーつまり中間レイヤを提供します。これにより、ストリーム構成をカスタマイズして、オンデマンドでキャプチャ リクエストを送信できます。

実装するファイル

アドバンスト エクステンダー実装に切り替えるには、ExtensionVersionImplisAdvancedExtenderImplemented() メソッドで true を返す必要があります。OEM は、拡張機能タイプごとに、対応するエクステンダー クラスを実装する必要があります。アドバンスト エクステンダー実装のファイルは、advanced パッケージに含まれています。

実装するエクステンダー クラス
夜間モード advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
自動 advanced/AutoAdvancedExtenderImpl.java
ボケ advanced/BokehAdvancedExtenderImpl.java
顔写真加工 advanced/BeautyAdvancedExtenderImpl.java

以下の例では、プレースホルダとして AdvancedExtenderImpl を使用しています。これは、実装する拡張機能のエクステンダー ファイルの名前に置き換えてください。

Camera2/X が extensions-interface を呼び出して 3 つのアプリフローを実現する仕組みを見てみましょう。

アプリフロー 1: 拡張機能の利用可能性を確認する

AdvancedAppFlow1

図 8. アドバンスト エクステンダーのアプリフロー 1

最初に、アプリは特定の拡張機能がサポートされているかどうかを確認します。

アプリフロー 2: 情報をクエリする

AdvancedAppFlow2

図 9. アドバンスト エクステンダーのアプリフロー 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: 拡張機能を有効化してプレビュー / 静止画撮影を行う

AdvancedAppFlow3

図 10. アドバンスト エクステンダーのアプリフロー 3

上の図は、アドバンスト エクステンダー タイプのプレビューと静止画撮影を開始するメインフローを示しています。各ステップを順に見てみましょう。

  1. SessionProcessorImpl インスタンス

    アドバンスト エクステンダーのコア実装は SessionProcessorImpl にあります。これは、カスタマイズされたセッション構成を提供し、キャプチャ リクエストを送信してプレビューおよび静止画撮影リクエストを開始します。AdvancedExtenderImpl.createSessionProcessor() が呼び出されて、SessionProcessorImpl インスタンスを返します。

  2. initSession

    SessionProcessorImpl.initSession() は、拡張機能のセッションを初期化します。ここで、リソースを割り当てて、CameraCaptureSession を準備するセッション構成を返します。

    入力パラメータに対して、Camera2/X は、プレビュー、静止画撮影、YUV 画像解析(任意)の出力サーフェス構成を指定します。この出力サーフェス構成(OutputSurfaceImpl)には、AdvancedExtenderImpl の以下のメソッドによって取得されるサーフェス、サイズ、画像形式が含まれています。

    • getSupportedPreviewOutputResolutions()
    • getSupportedCaptureOutputResolutions()
    • getSupportedYuvAnalysisResolutions()

    Camera2SessionConfigImpl インスタンスを返す必要があります。これは、Camera2OutputConfigImpl インスタンスのリストと、CameraCaptureSession を構成するために使用されるセッション パラメータで構成されます。OEM は、Camera2/X によって渡される出力サーフェスに、正しいカメラ画像を出力する必要があります。出力を有効化するオプションは次のとおりです。

    • カメラ HAL で処理する:SurfaceOutputConfigImpl 実装を使用して、出力サーフェスを CameraCaptureSession に直接追加できます。これにより、指定された出力サーフェスがカメラ パイプラインに対して構成され、カメラ HAL が画像を処理できるようになります。
    • 中間 ImageReader サーフェス(RAW、YUV など)を処理する: ImageReaderOutputConfigImpl インスタンスを使用して、中間 ImageReader サーフェスを CameraCaptureSession に追加します。

      中間画像を処理して、結果の画像を出力サーフェスに書き込む必要があります。

    • Camera2 サーフェス共有を使用する: もう一つの Camera2OutputConfigImpl インスタンスの getSurfaceSharingOutputConfigs() メソッドに Camera2OutputConfigImpl インスタンスを追加することにより、もう一つのサーフェスとのサーフェス共有を使用します。サーフェスの形式とサイズが同一である必要があります。

    SurfaceOutputConfigImplImageReaderOutputConfigImpl を含むすべての Camera2OutputConfigImpl は一意の ID(getId())を持つ必要があります。この ID は、ターゲット サーフェスを指定して ImageReaderOutputConfigImpl から画像を取得するために使用されます。

  3. onCaptureSessionStart および RequestProcessorImpl

    CameraCaptureSession が開始されてカメラ フレームワークが onConfigured() を呼び出すと、Camera2/X は Camera2 リクエスト ラッパー RequestProcessImpl を使用して SessionProcessorImpl.onCaptureSessionStart() を呼び出します。Camera2/X は RequestProcessImpl を実装します。これにより、ImageReaderOutputConfigImpl が使用されている場合は、キャプチャ リクエストを実行して画像を取得できます。

    リクエストの実行に関しては、RequestProcessImpl API は Camera2 CameraCaptureSession API と似ています。ただし、以下の点が異なります。

    • ターゲット サーフェスが Camera2OutputConfigImpl インスタンスの ID で指定される。
    • ImageReader の画像を取得する機能。

    指定された Camera2OutputConfigImpl ID で RequestProcessorImpl.setImageProcessor() を呼び出して、画像を受信する ImageProcessorImpl インスタンスを登録できます。

    Camera2/X が SessionProcessorImpl.onCaptureSessionEnd() を呼び出した後、RequestProcessImpl インスタンスは無効になります。

  4. プレビューの開始と写真の撮影

    アドバンスト エクステンダー実装では、RequestProcessorImpl インターフェースを介してキャプチャ リクエストを送信できます。Camera2/X は、SessionProcessorImpl#startRepeatingSessionProcessorImpl#startCapture を呼び出すことにより、プレビューの反復リクエストの開始と静止画撮影シーケンスの開始をそれぞれ OEM に通知します。プレビュー リクエストと静止画撮影リクエストに応じるには、キャプチャ リクエストを送信する必要があります。

    また、Camera2/X は、SessionProcessorImpl#setParameters を介してキャプチャ リクエスト パラメータを設定します。これらのリクエスト パラメータ(パラメータがサポートされている場合)は、反復リクエストと単一リクエストの両方で設定する必要があります。

    OEM は、少なくとも CaptureRequest.JPEG_ORIENTATIONCaptureRequest.JPEG_QUALITY をサポートする必要があります。extensions-interface 1.3.0 は、以下のメソッドによって公開されるリクエストキーと結果キーをサポートしています。

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys()

    デベロッパーが getAvailableCaptureRequestKeys リストでキーを設定している場合、OEM はパラメータを有効化して、getAvailableCaptureResultKeys リストのキーがキャプチャ結果に含まれるようにする必要があります。

  5. startTrigger

    SessionProcessorImpl.startTrigger() が呼び出され、CaptureRequest.CONTROL_AF_TRIGGERCaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER などのトリガーが起動されます。AdvancedExtenderImpl.getAvailableCaptureRequestKeys() でアドバタイズされていないキャプチャ リクエスト キーは無視してかまいません。

    startTrigger() は、extensions-interface 1.3.0 以降でサポートされています。これにより、アプリは拡張機能を使用して、タップしてフォーカスとフラッシュを実装できます。

  6. クリーンアップ

    キャプチャ セッションが終了すると、CameraCaptureSession が閉じる前に SessionProcessorImpl.onCaptureSessionEnd() が呼び出されます。キャプチャ セッションが閉じられた後、deInitSession() はクリーンアップを実行します。

プレビュー、静止画撮影、画像解析のサポート

プレビューと静止画撮影の両方のユースケースに拡張機能を適用する必要があります。ただし、レイテンシが大きすぎてプレビューをスムーズに表示できない場合は、静止画撮影のみに拡張機能を適用してもかまいません。

ベーシック エクステンダー タイプの場合は、プレビューの拡張機能を有効化するかどうかにかかわらず、特定の拡張機能について ImageCaptureExtenderImplPreviewExtenderImpl の両方を実装する必要があります。また、多くの場合、アプリは YUV ストリームを使用して画像コンテンツを解析し、QR コードやテキストの検出などを行います。このユースケースを適切にサポートするには、CameraCaptureSession を構成するプレビュー、静止画撮影、YUV_420_888 ストリームの組み合わせをサポートする必要があります。つまり、プロセッサを実装する場合は、3 つの YUV_420_888 ストリームの組み合わせをサポートする必要があります。

アドバンスト エクステンダーの場合、Camera2/X は 3 つの出力サーフェスを SessionProcessorImpl.initSession() 呼び出しに渡します。これらの出力サーフェスは、それぞれプレビュー、静止画撮影、画像解析に使用されます。プレビューと静止画撮影の出力サーフェスに有効な出力が表示されることを確認する必要があります。画像解析の出力サーフェスについては、null 以外の場合にのみ機能することを確認してください。実装が画像解析ストリームをサポートできない場合は、AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() で空のリストを返すことができます。そうすれば、画像解析の出力サーフェスは SessionProcessorImpl.initSession() で常に null になります。

動画撮影のサポート

現在のカメラ拡張機能アーキテクチャは、プレビューと静止画撮影のユースケースのみをサポートしています。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 タイプを使用している拡張機能は、シーンの状態に応じて HDRNIGHT など、拡張機能タイプを動的に切り替えるため、カメラ拡張機能アプリは 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();

リアルタイムでの静止画撮影レイテンシの推定をサポートするには、次のように実装します。

キャプチャ処理の進行状況コールバック

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
    }
  }
…
}

キャプチャ処理の進行状況コールバックをサポートするには、拡張機能ベンダー実装で現在の進行状況の値を指定して次のコールバックを呼び出す必要があります。

静止画撮影のポストビュー

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
  • バージョンの確認
    • ExtensionVersionImpl
  • ベーシック エクステンダー
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • ライブラリの初期化
    • InitializerImpl
  • サポートされている解像度の公開
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • キャプチャ レイテンシの推定値の取得
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • サポートされているキャプチャ リクエスト キー / 結果キーの公開
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys および getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys および getAvailableCaptureResultKeys
    • PreviewImageProcessorImplCaptureProcessorImplProcessResultImpl を受け取る新しい process() 呼び出し
    • トリガータイプのリクエストのサポート
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • 拡張機能固有のメタデータ
  • 動的な静止画撮影レイテンシの推定
  • キャプチャ処理の進行状況コールバック
  • 静止画撮影のポストビュー
  • SurfaceView 出力のサポート
  • ベンター固有のセッション タイプ

リファレンス実装

frameworks/ex では、以下のリファレンス OEM ベンダー ライブラリの実装を利用できます。

  • advancedSample: アドバンスト エクステンダーの基本的な実装です。

  • sample: ベーシック エクステンダーの基本的な実装です。

  • service_based_sample: Service でカメラ拡張機能をホストする方法を示す実装です。この実装には次のコンポーネントが含まれています。

    • oem_library: Extensions-Interface を実装する Camera2 Extensions API と CameraX Extensions API のためのカメラ拡張機能 OEM ライブラリです。これは、Extensions-Interface からの呼び出しをサービスに転送するパススルーとして機能します。このライブラリには、サービスと通信するための AIDL ファイルとラッパークラスも用意されています。

      アドバンスト エクステンダーはデフォルトで有効になっています。ベーシック エクステンダーを有効にするには、false を返すように ExtensionsVersionImpl#isAdvancedExtenderImplemented を変更します。

    • extensions_service: 拡張機能サービスのサンプル実装です。ここに実装を追加してください。サービスに実装するためのインターフェースは Extensions-Interface と同様です。たとえば、IAdvancedExtenderImpl.Stub を実装すると、AdvancedExtenderImpl と同じオペレーションが実行されます。ImageTotalCaptureResult を Parcelable にするには、ImageWrapperTotalCaptureResultWrapper が必要です。

デバイスにベンダー ライブラリをセットアップする

OEM ベンダー ライブラリはアプリに組み込まれず、Camera2/X によって実行時にデバイスから読み込まれます。CameraX では、androidx.camera.extensions.impl ライブラリ(camera-extensions ライブラリの AndroidManifest.xml ファイルで定義されます)が CameraX の依存関係であり、実行時に読み込む必要のあることが <uses-library> タグによって宣言されます。Camera2 では、<uses-library> が実行時に同じ androidx.camera.extensions.impl ライブラリを読み込むことも宣言する拡張機能サービスがフレームワークによって読み込まれます。

これにより、拡張機能を使用するサードパーティ アプリが OEM ベンダー ライブラリを自動的に読み込むことが可能になります。OEM ライブラリはオプションとしてマークされているため、デバイス上にライブラリを持たないデバイスでもアプリを実行できます。デバイス メーカーがデバイスに OEM ライブラリを配置してアプリで検出できるようにしている場合、Camera2/X は、アプリがカメラ拡張機能を使用しようとしたときにこの動作を自動的に処理します。

デバイスに OEM ライブラリをセットアップする手順は次のとおりです。

  1. /etc/permissions/ANY_FILENAME.xml の形式を使用して、<uses-library> タグで必要となる権限ファイルを追加します。たとえば /etc/permissions/camera_extensions.xml のようになります。このディレクトリ内のファイルは、<uses-library> で指定されたライブラリとデバイス上の実際のファイルパスとのマッピングを提供します。
  2. 以下の例を使用して、必要な情報をファイルに追加します。

    • name は、CameraX によって検索されるライブラリであるため、androidx.camera.extensions.impl である必要があります。
    • 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 に設定する必要があります。これにより、デバイスが拡張機能をサポートしているかどうかを照会できます。これを行うには、デバイスの make ファイルに次の行を追加します。

PRODUCT_VENDOR_PROPERTIES += \
    ro.camerax.extensions.enabled=true \

検証

開発段階で OEM ベンダー ライブラリの実装をテストするには、androidx-main/camera/integration-tests/extensionstestapp/ にあるサンプルアプリを使用します。このアプリでは、さまざまなベンダー拡張機能を実行できます。

実装が完成したら、カメラ拡張機能検証ツールを使用して自動テストと手動テストを実施し、ベンダー ライブラリが正しく実装されていることを検証します。

拡張撮影モードとカメラ拡張機能の違い

ボケ拡張機能は、カメラ拡張機能を使用して適用するほか、拡張撮影モードを使用して適用することもできます。拡張撮影モードは CONTROL_EXTENDED_SCENE_MODE キーで有効になります。実装について詳しくは、カメラのボケ表現をご覧ください。

拡張撮影モードには、Camera2 アプリのカメラ拡張機能ほど制限がありません。たとえば、拡張撮影モードは、柔軟性の高いストリームの組み合わせとキャプチャ リクエスト パラメータをサポートする通常の CameraCaptureSession インスタンスで有効にできます。それに対し、カメラ拡張機能がサポートするストリーム タイプは一定数のみで、キャプチャ リクエスト パラメータのサポートも制限されています。

拡張撮影モードの短所は、カメラの HAL にしか実装できない点です。そのため、アプリ デベロッパーが使用可能なすべての直交制御で動作することを検証する必要があります。

アプリは特定の API を使用してボケ効果を有効にする方がよいこともあるため、拡張撮影モードとカメラ拡張機能の両方を使用してボケ効果を適用することをおすすめします。 拡張撮影モードがアプリで最も柔軟にボケ拡張機能を有効にする方法であるため、拡張撮影モードから使用することをおすすめします。その後、拡張撮影モードをベースとしてカメラ拡張機能のインターフェースを実装できます。たとえば、画像を処理するためにアプリレイヤでポスト プロセッサを実行する必要があるため、カメラ HAL にボケ効果を実装することが難しい場合は、カメラ拡張機能のインターフェースを使用してボケ拡張機能を実装することをおすすめします。

よくある質問(FAQ)

API レベルに制限はありますか?

はい。API レベルは、OEM ベンダー ライブラリの実装に必要な Android API 機能セットによって異なります。たとえば、ExtenderStateListener.onPresetSession() では、SessionConfiguration.setSessionParameters() 呼び出しを使用してタグのベースライン セットを設定します。この呼び出しは API レベル 28 以上でのみ使用できます。特定のインターフェース メソッドの詳細については、API リファレンス ドキュメントをご覧ください。