デバイスをウェブカメラとして使用する

Android 14-QPR1 以降を搭載したデバイスには、そのデバイスを USB ウェブカメラとして使用できる機能が付いています。この機能をサポートする Android デバイスは、UVC デバイスとしてアドバタイズされており、Linux、macOS、Windows、ChromeOS などのオペレーティング システムを持つさまざまな USB ホストがデバイスのカメラをウェブカメラとして使用することを可能にします。DeviceAsWebcam サービスは、デバイスをウェブカメラとして使用できるこの機能をサポートしています。

DeviceAsWebcam サービス

AOSP の DeviceAsWebcam サービスには、ユーザーが撮影範囲を指定できるプレビュー アクティビティ(DeviceAsWebcamPreview.java)の機能が含まれています。プレビュー アクティビティにおいて、ユーザーは以下のことができます。

  • ストリーミングを開始する前に、ホストマシン上でウェブカメラのフィードがどのように見えるかをプレビューできます。

  • 以下の方法で、ホストに送信されるウェブカメラ フィードをカスタマイズできます。

    • 前面カメラまたは背面カメラのどちらをストリーミングするかを選択します。
    • スライダーまたはボタンを使用して、ズームレベルを選択します。
    • プレビュー画面の特定の部分をタップして、その部分にピントを合わせたり、ピントを外したりします。

プレビュー アクティビティは、TalkBackSwitch AccessVoice Access などの Android の一般的なユーザー補助機能に対応しています。

ホストにストリーミングされているウェブカメラのフィード

図 1. ホストにストリーミングされているウェブカメラのフィードおよびフィードを制御しているプレビュー

アーキテクチャ

デバイスをウェブカメラとして使用することをサポートするアーキテクチャは、図 2 に示されているとおりです。以下は、DeviceAsWebcam サービスと Android フレームワークの残りの部分のインタラクション フローです。

  1. ユーザーが設定アプリで USB ウェブカメラを選択します。
  2. 設定アプリが UsbManager クラスを介して、system_server にバインダー呼び出しを送信し、FUNCTION_UVC が選択されたことを通知します。
  3. システム サーバーは、以下の処理を行います。
    1. setUsbFunctions HAL インターフェース呼び出しを通じて、USB ガジェット HAL に UVC ガジェット機能を取得するよう通知します。
    2. ConfigFs を使用して UVC ガジェット ドライバを構成するよう、USB ガジェット HAL に通知します。
  4. ガジェット HAL からコールバックを受信すると、system_server はフレームワークにブロードキャストを送信し、DeviceAsWebcam サービスがそれを受け取ります。
  5. USB ガジェット ドライバは、V4L2 ノード /dev/video* を介してホストから構成コマンドを受信すると、ウェブカメラのストリーミングを開始します。

DeviceAsWebcam のアーキテクチャ

図 2. DeviceAsWebcam のアーキテクチャ

実装

このセクションでは、Android デバイスをウェブカメラとして使用することをサポートする方法について説明します。

カーネル サポート

Android 14 以降では、汎用カーネル イメージ(GKI)により UVC ガジェット ドライバがデフォルトで有効になります(詳細は AOSP パッチを参照)。

ガジェット HAL で UVC をサポートする

Android 14 以降では、GadgetFunction.aidl HAL インターフェースに UVC 機能が含まれています。ガジェット HAL では、UVC ガジェットは MTP や ADB などの他の ConfigFS 機能と同じように ConfigFS にマウントされます。

ガジェット HAL を実装するには、UVC 機能が ConfigFS にマウントされるよう変更する必要があります。以下は、UVC 機能をサポートするガジェット HAL の実装についてのスニペットの例です。

UsbGadget::setCurrentUsbFunctions(long functions) {
   ...
   // Existing functions
   if ((functions & GadgetFunction::MTP) != 0) {
       ...
       linkFunction("ffs.mtp"); // Mount to ConfigFS
       ...
   }
   ...
   // UVC function follows the same pattern!
   if ((functions & GadgetFunction::UVC) != 0) {
       ...
       linkFunction("uvc.0"); // Mount to ConfigFS
       ...
   }
   ...
}

デバイスをウェブカメラとして使用する際は、USB ガジェット HAL が適切な VID と PID の組み合わせをアドバタイズしていることを確認してください。

すべての UVC ロジックは、ベンダーの init または DeviceAsWebcam サービスにあるため、UVC 機能を ConfigFS にシンボリック リンクする以外、ガジェット HAL に UVC 特有のロジックは必要ありません。

実装に関する詳しいガイダンスについては、AOSP の以下のサンプルコードを参照してください。

UVC 構成で ConfigFS を設定する

Android ウェブカメラでサポートされている形式、サイズ、フレームレートを UVC ガジェット ドライバに知らせるには、UVC 構成で ConfigFS を設定します。詳細については、ConfigFS UVC ガジェット ABI に関するアップストリームの Linux のドキュメントをご覧ください。

以下の例は、ベンダー init で UVC ガジェット ドライバを設定する方法を示しています(AOSP のコード スニペット)。

# uvc function
   mkdir /configfs_path/functions/uvc.0
   write /configfs_path/functions/uvc.0/function_name "Android Webcam"
   write /configfs_path/functions/uvc.0/streaming_maxpacket 3072
   # setup control params
   mkdir /configfs_path/functions/uvc.0/control/header/h
   symlink /configfs_path/functions/uvc.0/control/header/h \
                /configfs_path/functions/uvc.0/control/class/fs/h
   symlink /configfs_path/functions/uvc.0/control/header/h \
                /configfs_path/functions/uvc.0/control/class/ss/h
   # advertise 1080p resolution for webcam encoded as mjpeg
   mkdir /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/wHeight 1080
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/wWidth 1920
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwMaxVideoFrameBufferSize 4147200
   # advertise 30 fps support for 1080p.
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwDefaultFrameInterval 333333
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwFrameInterval "333333"
   # setup streaming params
   mkdir /configfs_path/functions/uvc.0/streaming/header/h
   symlink /configfs_path/functions/uvc.0/streaming/mjpeg/m \
                /configfs_path/functions/uvc.0/streaming/header/h/m
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /configfs_path/functions/uvc.0/streaming/class/fs/h
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /configfs_path/functions/uvc.0/streaming/class/hs/h
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /config/usb_gadget/g1/functions/uvc.0/streaming/class/ss/h
   # ...

このスニペットにより、UVC ガジェット ドライバが 1080p MJPEG ストリームを 30 fps でアドバタイズするよう設定できます。これらの設定は、USB ホストがサポートされている解像度とフレームレートを問い合わせた際に通知されます。

以下は、ウェブカメラがアドバタイズする構成を選択する際の一般的なガイドラインです。

  • DeviceAsWebcam サービスでサポートされているストリーム形式は、MJPEG と非圧縮 YUYV の 2 つです。
  • USB 2.0 は、480 Mbps(60 MBps)のデータ転送をサポートしています。つまり、30 fps の場合、各フレームの最大サイズは 2 MB、60 fps の場合、最大サイズは 1 MB である必要があります。
    • 非圧縮ストリーム(YUYV): YUYV は 1 ピクセルあたり 2 バイトであるため、30 fps の場合、サポートされる最大フレームサイズは 720p です。
    • 圧縮 MJPEG ストリーム: YUV の圧縮率を 1:10 と仮定すると、USB 2.0 は 4K(1 フレームあたり 1.18 MB)をサポートできます。
  • メインの前面カメラと背面カメラを搭載したデバイスは、アドバタイズされているすべてのフレームサイズをサポートする必要があります。これは、ユーザーがプレビュー UI を使用してカメラ ID を切り替えることができるためです。MJPEG ストリームに関しては、480p(640 x 480)、720p(1280 x 820)、1080p(1920 x 1080)のフレームサイズをアドバタイズすることをベンダーに推奨しています。これらがホストアプリで一般的に使用されているサイズであるためです。
  • メインの前面カメラと背面カメラを搭載したデバイスは、アドバタイズされているすべてのフレームレートをサポートする必要があります。ベンダーには、30 fps をサポートすることを強く推奨しています。

ウェブカメラのストリーム構成の追加(ConfigFS)に関する例については、AOSP のサンプルパッチを参照してください。

ビルド時にウェブカメラを有効化する

DeviceAsWebcam サービスを有効にするには、device.mk ファイルで ro.usb.uvc.enabled のシステム プロパティを true に設定する必要があります。

# Enable UVC support
PRODUCT_VENDOR_PROPERTIES += \
    ro.usb.uvc.enabled=true

このシステム プロパティを有効にすると、図 3 に示すように、設定アプリの [USB の設定] にウェブカメラのオプションが表示されます。ウェブカメラが選択されると、ホストデバイスに USB ウェブカメラとして Android デバイスが表示されます。

図 3. 設定アプリの [USB の設定]

以下のコマンドを使用して、ADB 経由でデバイスを USB ウェブカメラのモードに設定することもできます。

adb shell svc usb setFunctions uvc

電力や熱に関する懸念を考慮する

デバイスをウェブカメラとして使用すると、デバイスのカメラがオンになっている状態が 1 日に何時間も続く可能性があるため、デバイスの消費電力と熱を一定の制限内に抑えるための対策を行うことをおすすめします。以下は、消費電力を制限内に抑えるために推奨される解決策です。

  • カメラ HAL の電力パフォーマンスを向上させるために、DeviceAsWebcam サービスで STREAM_USE_CASE_VIDEO_CALL を有効にします。
  • STREAM_USE_CASE_VIDEO_CALL を有効にしても、まだ消費電力が懸念される場合、DeviceAsWebcam サービスでは、物理ストリームを使用することで、消費電力をさらに削減することが可能です。ランタイム リソース オーバーレイ(RRO)を使って、どの物理カメラを使用するかを指定することができます。ただし、物理ストリームは動画の品質を著しく低下させ、ユーザーに混乱を与えるため、この解決策は最後の手段として使用してください。電力についての懸念に対する解決策としては、STREAM_USE_CASE_VIDEO_CALL の最適化をおすすめします。DeviceAsWebcam サービスがサポートする RRO の詳細については、readme.md をご覧ください。

    以下は、論理カメラ ID 0 の代わりに物理カメラ ID 3 を使用する際の RRO の設定例です。また、AOSP の例については、DeviceAsWebcamRaven をご覧ください。

    // For logical camera id 0 - use physical camera id 3
    {"0": {"3" : "UW"}}
    

確認

デバイス上の DeviceAsWebcam サービスの実装をテストするには、以下を使用します。

  • CTS 検証ツールによるウェブカメラのテスト: 形式、サイズ、フレームレートがデバイスでサポートされているかをテストします。
  • 手動テスト: ウェブカメラの機能がさまざまなホスト オペレーティング システム上のさまざまなホストアプリで動作するかをテストします。

既知の問題

以下は、DeviceAsWebcam サービスに関する既知の問題です。