互換性のあるメディアトランスコーディング

Android 12で導入された互換性のあるメディアトランスコーディングは、アプリとの互換性を維持しながら、デバイスがHEVCなどのビデオキャプチャに最新のストレージ効率の高いメディア形式を使用できるようにする機能です。この機能により、デバイスメーカーはデフォルトでAVCの代わりにHEVCを使用して、ストレージと帯域幅の要件を減らしながらビデオ品質を向上させることができます。互換性のあるメディアトランスコーディングが有効になっているデバイスの場合、Androidは、HEVCやHDRなどの形式で記録されたビデオ(最大1分)を、その形式をサポートしていないアプリで開いたときに自動的に変換できます。これにより、デバイスでビデオが新しい形式でキャプチャされた場合でも、アプリが機能するようになります。

互換性のあるメディアトランスコーディング機能はデフォルトでオフになっています。メディアトランスコーディングをリクエストするには、アプリはメディア機能を宣言する必要があります。メディア機能の宣言の詳細については、AndroidDevelopersサイトの互換性のあるメディアトランスコーディングを参照してください。

使い方

互換性のあるメディアトランスコーディング機能は、次の2つの主要部分で構成されています。

  • メディアフレームワークのトランスコーディングサービス:これらのサービスは、ハードウェアを使用してファイルをある形式から別の形式に変換し、低遅延で高品質の変換を実現します。これには、トランスコーディングAPI、トランスコーディングサービス、カスタムフィルター用のOEMプラグイン、およびハードウェアが含まれます。詳細については、アーキテクチャの概要を参照してください。
  • メディアプロバイダーの互換性のあるメディアトランスコーディング機能:メディアプロバイダーにあるこのコンポーネントは、メディアファイルにアクセスするアプリをインターセプトし、アプリの宣言された機能に基づいて元のファイルまたはトランスコードされたファイルのいずれかを提供します。アプリがメディアファイルの形式をサポートしている場合、特別な処理は必要ありません。アプリがこの形式をサポートしていない場合、アプリがファイルにアクセスすると、フレームワークはファイルをAVCなどの古い形式に変換します。

図1は、メディアトランスコーディングプロセスの概要を示しています。

互換性のあるメディアトランスコーディングプロセス

図1.互換性のあるメディアトランスコーディングの概要。

サポートされている形式

互換性のあるメディアトランスコーディング機能は、次のフォーマット変換をサポートします。

  • HEVC(8ビット)からAVCへ:コーデック変換は、1つのメディアコーデックデコーダーと1つのメディアコードエンコーダーを接続することによって実行されます。
  • HDR10 +(10ビット)からAVC(SDR): HDRからSDRへの変換は、mediacodecインスタンスと、デコーダーインスタンスへのベンダープラグインフックを使用して実行されます。詳細については、 HDRからSDRへのエンコーディングを参照してください。

サポートされているコンテンツソース

互換性のあるメディアトランスコーディング機能は、プライマリ外部ボリュームのDCIM/Camera/フォルダーに保存されているネイティブOEMカメラアプリによって生成されたデバイス上のメディアをサポートします。この機能は、セカンダリストレージ上のメディアをサポートしていません。電子メールまたはSDカードを介してデバイスに渡されるコンテンツはサポートされていません。

アプリは、さまざまなファイルパスに基づいてファイルにアクセスします。次に、トランスコーディングが有効またはバイパスされるファイルパスについて説明します。

  • トランスコーディングが有効:

    • MediaStoreAPIを介したアプリアクセス
    • Javaやネイティブコードを含む直接ファイルパスAPIを介したアプリアクセス
    • Storage Access Framework(SAF)を介したアプリアクセス
    • OS共有シートのインテントを介したアプリアクセス。 (MediaStore URIのみ)
    • 電話からPCへのMTP/PTPファイル転送
  • トランスコーディングがバイパスされました:

    • SDカードをイジェクトしてデバイスからファイルを転送する
    • 近くの共有やBluetooth転送などのオプションを使用して、デバイスからデバイスにファイルを転送します。

トランスコーディング用にカスタマイズされたファイルパスを追加する

デバイスメーカーは、オプションで、 DCIM/ディレクトリの下にメディアトランスコーディング用のファイルパスを追加できます。 DCIM/ディレクトリ外のパスはすべて拒否されます。このようなファイルパスの追加は、通信事業者の要件または地域の規制を満たすために必要になる場合があります。

ファイルパスを追加するには、トランスコードパスランタイムリソースオーバーレイ(RRO)config_supported_transcoding_relative_pathsを使用します。次に、ファイルパスを追加する方法の例を示します。

<string-array name="config_supported_transcoding_relative_paths" translatable="false">
    <item>DCIM/JCF/</item>
</string-array>

構成されたファイルパスを確認するには、次を使用します。

adb shell dumpsys activity provider com.google.android.providers.media.module/com.android.providers.media.MediaProvider | head -n 20

アーキテクチャの概要

このセクションでは、メディアトランスコーディング機能のアーキテクチャについて説明します。

メディアトランスコーディングアーキテクチャ

図2.メディアトランスコーディングアーキテクチャ。

メディアトランスコーディングアーキテクチャは、次のコンポーネントで構成されています。

  • MediaTranscodingManagerシステムAPI:クライアントがMediaTranscodingサービスと通信できるようにするインターフェイス。 MediaProviderモジュールはこのAPIを使用します。
  • MediaTranscodingService:クライアント接続を管理し、トランスコーディング要求をスケジュールし、 TranscodingSessionsの簿記を管理するネイティブサービス。
  • MediaTranscoder:トランスコーディングを実行するネイティブライブラリ。このライブラリは、モジュールと互換性があるようにメディアフレームワークNDKの上に構築されています。

互換性のあるメディアトランスコーディング機能は、サービスとメディアトランスコーダーの両方でトランスコーディングメトリックをログに記録します。クライアント側とサービス側のコードはMediaProviderモジュールにあり、タイムリーなバグ修正と更新を可能にします。

ファイルアクセス

互換性のあるメディアトランスコーディングは、スコープ付きストレージに使用されるFilesystem in Userspace(FUSE)ファイルシステムの上に構築されています。 FUSEを使用すると、MediaProviderモジュールは、ユーザースペースでのファイル操作を調べ、アクセスを許可、拒否、または編集するポリシーに基づいてファイルへのアクセスをゲートできます。

アプリがファイルにアクセスしようとすると、FUSEデーモンがアプリからのファイル読み取りアクセスを傍受します。アプリが新しい形式(HEVCなど)をサポートしている場合は、元のファイルが返されます。アプリがその形式をサポートしていない場合、ファイルは古い形式(AVCなど)にトランスコードされるか、トランスコードされたバージョンが利用可能な場合はキャッシュから返されます。

トランスコードされたファイルをリクエストする

互換性のあるメディアトランスコード機能はデフォルトで無効になっています。つまり、デバイスがHEVCをサポートしている場合、Androidは、マニフェストファイルまたは強制トランスコードリストでアプリによって指定されない限り、ファイルをトランスコードしません。

アプリは、次のオプションを使用してトランスコードされたアセットをリクエストできます。

  • マニフェストファイルでサポートされていない形式を宣言します。詳細については、「リソースで機能宣言する」および「コードで機能を宣言する」を参照してください。
  • MediaProviderモジュールに含まれている強制トランスコードリストにアプリを追加します。これにより、マニフェストファイルを更新していないアプリのトランスコーディングが可能になります。アプリがサポートされていない形式でマニフェストファイルを更新したら、強制トランスコードリストから削除する必要があります。デバイスメーカーは、パッチを送信する、バグを報告することで、強制トランスコードリストに追加または削除するアプリを指定できます。 Androidチームは定期的にリストを確認し、リストからアプリを削除する場合があります。
  • 実行時にアプリ互換性フレームワークでサポートされている形式を無効にします(ユーザーは[設定]でアプリごとにこれを無効にすることもできます)。
  • openTypedAssetFileDescriptor APIでサポートされていない形式を明示的に指定しながら、 MediaStoreでファイルを開きます。

USB転送(デバイスからPC)の場合、トランスコーディングはデフォルトで無効になっていますが、ユーザーは、図3に示すように、 USB設定設定画面で[ビデオをAVCに変換]トグルを使用してトランスコーディングを有効にすることを選択できます。

トグルしてメディアトランスコーディングを有効にする

図3.切り替えてUSB設定画面でメディアトランスコーディングを有効にします。

トランスコードされたファイルの要求に関する制限

トランスコーディングリクエストがシステムリソースを長期間ロックするのを防ぐために、トランスコーディングセッションをリクエストするアプリは次のように制限されています。

  • 10回の連続セッション
  • 合計実行時間は3分です

アプリがこれらすべての制限を超えると、フレームワークは元のファイル記述子を返します。

デバイス要件

互換性のあるメディアトランスコーディング機能をサポートするには、デバイスが次の要件を満たしている必要があります。

  • デバイスでは、ネイティブカメラアプリでデフォルトでHEVCエンコーディングが有効になっています
  • (HDRからSDRへのトランスコーディングをサポートするデバイス)デバイスはHDRビデオキャプチャをサポートします

メディアトランスコーディングのデバイスパフォーマンスを確保するには、ビデオハードウェアとストレージの読み取り/書き込みアクセスパフォーマンスを最適化する必要があります。メディアコーデックが1に等しい優先度で設定されている場合、コーデックは可能な限り最高のスループットで動作する必要があります。トランスコーディングのパフォーマンスは最低200fpsを達成することをお勧めします。ハードウェアのパフォーマンスをテストするには、 frameworks/av/media/libmediatranscoding/transcoder/benchmarkでメディアトランスコーダーベンチマークを実行します。

検証

互換性のあるメディアトランスコーディング機能を検証するには、次のCTSテストを実行します。

  • android.media.mediatranscoding.cts
  • android.mediaprovidertranscode.cts

メディアトランスコーディングをグローバルに有効にする

メディアトランスコーディングフレームワークまたはトランスコーディングを使用したアプリの動作をテストするには、互換性のあるメディアトランスコーディング機能をグローバルに有効または無効にします。 [設定]>[システム]>[開発者]>[メディアトランスコード開発者オプション]ページで、[トランスコードのデフォルトを上書きする]トグルをオンに設定してから、[トランスコードを有効にする]トグルをオンまたはオフに設定します。この設定を有効にすると、開発中のアプリ以外のアプリのバックグラウンドでメディアトランスコーディングが発生する可能性があります。

トランスコーディングステータスを確認する

テスト中に、次のADBシェルコマンドを使用して、現在および過去のトランスコーディングセッションを含むトランスコーディングステータスを確認できます。

adb shell dumpsys media.transcoding

ビデオの長さの制限を拡張する

テストの目的で、次のコマンドを使用して、トランスコーディングの1分間のビデオ長の制限を拡張できます。このコマンドを実行した後、再起動が必要になる場合があります。

adb shell device_config put storage_native_boot transcode_max_duration_ms <LARGE_NUMBER_IN_MS>

AOSPのソースとリファレンス

以下は、互換性のあるメディアトランスコーディングに関連するAOSPソースコードです。

HDRからSDRへのエンコーディング

HDRからSDRへのエンコードをサポートするために、デバイスメーカーは/platform/frameworks/av/media/codec2/hidl/plugin/にあるAOSPサンプルコーデック2.0フィルタープラグインを使用できます。このセクションでは、フィルタープラグインの動作、プラグインの実装方法、およびプラグインのテスト方法について説明します。

デバイスにHDRからSDRへのエンコードをサポートするプラグインが含まれていない場合、HDRビデオにアクセスするアプリは、マニフェストで宣言されているアプリのメディア機能に関係なく、元のファイル記述子を取得します。

使い方

このセクションでは、コーデック2.0フィルタープラグインの一般的な動作について説明します。

バックグラウンド

Androidは、コーデック2.0インターフェースとandroid.hardware.media.c2インターフェースの間にandroid::hardware::media::c2のアダプテーションレイヤー実装を提供します。フィルタープラグインの場合、AOSPには、デコーダーをフィルタープラグインと一緒にラップするラッパーメカニズムが含まれています。 MediaCodecは、これらのラップされたコンポーネントをフィルタリング機能を備えたデコーダーとして認識します。

概要

FilterWrapperクラスは、ベンダーコーデックを取得し、ラップされたコーデックをmedia.c2アダプテーション層に戻します。 FilterWrapperクラスは、 FilterWrapper::Plugin APIを介してlibc2filterplugin.soをロードし、プラグインから使用可能なフィルターを記録します。作成時に、 FilterWrapperは使用可能なすべてのフィルターをインスタンス化します。バッファを変更するフィルタのみが開始時に開始されます。

フィルタプラグインアーキテクチャ

図1.フィルタープラグインアーキテクチャ。

フィルタープラグインインターフェース

FilterPlugin.hインターフェースは、フィルターを公開するために次のAPIを定義します。

  • std::shared_ptr<C2ComponentStore>getComponentStore()

    フィルタを含むC2ComponentStoreオブジェクトを返します。これは、ベンダーのコーデック2.0実装が公開しているものとは別のものです。通常、このストアには、 FilterWrapperクラスで使用されるフィルターのみが含まれます。

  • bool describe(C2String name, Descriptor *desc)

    C2ComponentStoreから入手できるものに加えて、フィルターについて説明します。次の説明が定義されています。

    • controlParam :フィルターの動作を制御するパラメーター。たとえば、HDRからSDRへのトーンマッパーの場合、制御パラメーターはターゲット伝達関数です。
    • ImpactedParams:フィルタリング操作のaffectedParamsを受けるパラメーター。たとえば、HDRからSDRへのトーンマッパーの場合、影響を受けるパラメータは色の側面です。
  • bool isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf)

    フィルタコンポーネントがバッファを変更した場合はtrueを返します。たとえば、ターゲット伝達関数がSDRで、入力伝達関数がHDR(HLGまたはPQ)の場合、トーンマッピングフィルターはtrueを返します。

FilterWrapperの詳細

このセクションでは、 FilterWrapperクラスの詳細について説明します。

創造

ラップされたコンポーネントは、作成時に基礎となるデコーダーとすべての定義済みフィルターをインスタンス化します。

クエリと構成

ラップされたコンポーネントは、フィルターの説明に従って、着信パラメーターをクエリまたは構成要求から分離します。たとえば、フィルター制御パラメーターの構成は対応するフィルターにルーティングされ、フィルターからの影響を受けるパラメーターは、(影響を受けないパラメーターを持つデコーダーから読み取る代わりに)クエリに存在します。

クエリと構成

図2.クエリと構成。

始める

開始時に、ラップされたコンポーネントはデコーダーとバッファーを変更するすべてのフィルターを開始します。フィルタが有効になっていない場合、ラップされたコンポーネントはデコーダとパススルーバッファを開始し、デコーダ自体にコマンドを送信します。

バッファ処理

バッファ処理

図3.バッファー処理。

ラップされたデコーダーにキューに入れられたバッファーは、基になるデコーダーに送られます。ラップされたコンポーネントは、 onWorkDone_nb()コールバックを介してデコーダーから出力バッファーを取得し、それをフィルターにキューに入れます。最後のフィルターからの最終出力バッファーがクライアントに報告されます。

このバッファー処理を機能させるには、ラップされたコンポーネントがC2PortBlockPoolsTuningを最後のフィルターに構成して、フレームワークが予想されるブロックプールからバッファーを出力するようにする必要があります。

停止、リセット、および解放

停止時に、ラップされたコンポーネントは、デコーダーと開始されたすべての有効なフィルターを停止します。リセットおよびリリース時に、すべてのコンポーネントは、有効かどうかに関係なく、リセットまたはリリースされます。

サンプルフィルタープラグインを実装する

プラグインを有効にするには、次の手順を実行します。

  1. FilterPluginインターフェースをライブラリに実装し、/ vendor / lib[64]/libc2filterplugin.soにドロップし/vendor/lib[64]/libc2filterplugin.so.
  2. 必要に応じて、 mediacodec.teに追加の権限を追加します。
  3. アダプテーションレイヤーをAndroid12に更新し、 media.c2サービスを再構築します。

プラグインをテストする

サンプルプラグインをテストするには、次の手順を実行します。

  1. デバイスを再構築してフラッシュします。
  2. 次のコマンドを使用してサンプルプラグインをビルドします。

    m sample-codec2-filter-plugin
    
  3. デバイスを再マウントし、ベンダープラグインの名前を変更して、コーデックサービスによって認識されるようにします。

    adb root
    adb remount
    adb reboot
    adb wait-for-device
    adb root
    adb remount
    adb
    push /out/target/<...>/lib64/sample-codec2-filter-plugin.so \
    
    /vendor/lib64/libc2filterplugin.so
    adb push
    /out/target/<...>/lib/sample-codec2-filter-plugin.so \
    
    /vendor/lib/libc2filterplugin.so
    adb reboot