レイテンシを削減するための設計

Android 4.1 リリースでは、低レイテンシのオーディオ出力パスを実現するために内部フレームワークが変更されました。パブリック クライアント API または HAL API に関する最小限の変更も含まれます。このドキュメントでは、時間の経過とともに変化を加えられてきた初期設計について説明します。デバイス OEM および SoC ベンダーが特定のデバイスおよびチップセットにこの設計を正しく実装する際に、初期設計を十分に理解しておくことが役立ちます。この記事はアプリケーション デベロッパー向けのものではありません。

トラックの作成

クライアントはオプションで、AudioTrack C++ コンストラクタの audio_output_flags_t パラメータのビット AUDIO_OUTPUT_FLAG_FAST または AudioTrack::set() を設定できます。現在、これが可能なクライアントは次のとおりです。

AudioTrack C++ の実装は、AUDIO_OUTPUT_FLAG_FAST リクエストを確認し、必要に応じてクライアント レベルでリクエストを拒否する場合があります。リクエストを渡すと判断した場合は、IAudioTrack ファクトリ メソッド IAudioFlinger::createTrack()track_flags_t パラメータの TRACK_FAST ビットを用いて渡します。

AudioFlinger オーディオ サーバーは、TRACK_FAST リクエストを確認し、必要に応じてサーバー レベルでリクエストを拒否する場合があります。そして、共有メモリ制御ブロックのビット CBLK_FAST を介して、リクエストが受け入れられたかどうかをクライアントに通知します。

この判断に影響する要因は次のとおりです。

  • この出力用の高速ミキサー スレッドが存在する(下記参照)
  • トラックするサンプルレート
  • このトラックのコールバック ハンドラを実行するクライアント スレッドが存在する
  • トラック バッファサイズ
  • 利用可能な高速トラック スロット(下記参照)

クライアントのリクエストが承認された場合、これは「高速トラック」と呼ばれます。それ以外の場合は、「通常トラック」と呼ばれます。

ミキサー スレッド

AudioFlinger は、通常のミキサー スレッドを作成する際に、高速ミキサー スレッドも作成するかどうかを決定します。通常ミキサーと高速ミキサーは特定のトラックには関連付けられず、トラックのセットに関連付けられます。通常のミキサー スレッドは常に存在します。高速ミキサー スレッドが存在する場合は、通常のミキサースレッドに従属し、その制御下で動作します。

高速ミキサー

機能

高速ミキサー スレッドには次のような機能があります。

  • 通常ミキサーのサブミックスおよび最大 7 つのクライアント高速トラックのミキシング
  • トラックごとの減衰

省略された機能:

  • トラックごとのサンプルレート変換
  • トラックごとのエフェクト
  • ミックスごとのエフェクト

周期

高速ミキサーは周期的に実行され、その周期は 2~3 ミリ秒(ms)、またはスケジューリングの安定性が求められる場合は 5 ms というわずかに長い周期が推奨されます。この数値は、バッファ パイプライン全体を考慮して合計レイテンシが 10 ミリ秒のオーダーになるように選択されており、より小さな値を取ることも可能ですが、CPU スケジューリングの予測可能性によっては消費電力が増加し、グリッチが発生する場合があります。最大値は 20 ミリ秒まで設定可能ですが、合計レイテンシが低下するため避ける必要があります。

スケジューリング

高速ミキサーは、高い SCHED_FIFO 優先度で実行されます。長時間の CPU 時間は必要ありませんが、スケジューリングのジッターを低くして頻繁に実行する必要があります。ジッターとはサイクル時間の変動、つまり、実際のサイクル時間と予想されるサイクル時間の差を表します。実行が遅すぎる場合、アンダーランによりグリッチが発生します。実行が早すぎる場合も、トラックがデータを提供する前に高速トラックから pull されるため、グリッチが発生します。

ブロック

HAL write() 以外は、高速ミキサー スレッドがブロックを行わないことが理想的です。高速ミキサー内で発生した他のブロックは、バグと見なされます。特に、ミューテックスは回避され、代わりに、非ブロック アルゴリズム(ロックフリー アルゴリズムとも呼ばれます)が使用されます。このトピックの詳細については、優先度の逆転を回避するを参照してください。

他のコンポーネントとの関係性

高速ミキサーはクライアントとの直接的なやり取りをほぼ行いません。特に、バインダー レベルのオペレーションは表示されませんが、クライアントの共有メモリ制御ブロックにはアクセスします。

高速ミキサーは、状態キューを介して通常ミキサーからコマンドを受け取ります。

トラック データを pull する以外のクライアントとのやり取りは、通常ミキサーが使用されます。

高速ミキサーのメインのシンクは音声 HAL です。

通常ミキサー

機能

次のすべての機能が有効です:

  • 最大 32 トラック
  • トラックごとの減衰
  • トラックごとのサンプルレート変換
  • エフェクト処理

周期

周期は、20 ミリ秒以上の高速ミキサー周期の最初の整数倍として計算されます。

スケジューリング

通常のミキサーは高い SCHED_OTHER 優先度で実行されます。

ブロック

通常ミキサーをブロックすることは許可されており、多くの場合は、各種のミューテックスとそのサブミックスを書き込むブロッキング パイプでブロックします。

他のコンポーネントとの関係性

通常ミキサーは、バインダー スレッド、オーディオ ポリシー マネージャー、高速ミキサー スレッド、クライアント トラックなど、外部と広範囲にやり取りを行います。

通常ミキサーのシンクは、高速ミキサーのトラック 0 に対するブロッキング パイプです。

フラグ

AUDIO_OUTPUT_FLAG_FAST ビットはヒントであり、リクエストが処理されるという保証はありません。

AUDIO_OUTPUT_FLAG_FAST は、クライアント レベルの概念です。これはサーバーには表示されません。

TRACK_FAST はクライアント > サーバーという概念です。