フレーム レート

フレームレート API を使用すると、アプリは目的のフレームを Android プラットフォームに通知できます Android 11(API レベル 30)以降をターゲットとするアプリで利用できます。 従来、ほとんどのデバイスは 1 つのディスプレイのリフレッシュ レートしかサポートしていませんでしたが、 60 Hz ですが、この点は変わりつつあります。現在、多くのデバイスが リフレッシュレートを使用できます一部のデバイスではシームレスなリフレッシュ レートがサポートされています 黒い画面が(通常は 1 秒ほど)表示されることもあります。

API の主な目的は、アプリがすべての機能をより有効に活用できるようにすることです。 ディスプレイのリフレッシュ レート。例: 24 Hz の動画を再生するアプリ setFrameRate() を呼び出すと、デバイスでディスプレイが変更されることがあります。 リフレッシュ レートを 60 Hz から 120 Hz に変更できます。この新しいリフレッシュレートにより 24 Hz の動画をジャダーなしで再生でき、3:2 プルダウンの 同じ動画を 60 Hz ディスプレイで再生できます。その結果 体験できます

基本的な使用方法

Android では、サーフェスにアクセスして操作する方法がいくつか用意されているため、 setFrameRate() API の複数のバージョン。API の各バージョンは、 他のパラメータと同じように機能します。

実際にサポートされているディスプレイのリフレッシュ レートをアプリで考慮する必要はありません。 これは、次の呼び出しによって取得できます。 Display.getSupportedModes() setFrameRate() を安全に呼び出すために必要です。たとえば、1 つのデバイスに が 60 Hz をサポートしている場合は、アプリが必要とするフレームレートで setFrameRate() を呼び出します。 アプリのフレームレートがそれより高くないデバイスは、 現在のディスプレイのリフレッシュ レート。

setFrameRate() の呼び出しによってディスプレイの更新が変更されるかどうかを確認する 表示変更通知に登録するには、 DisplayManager.registerDisplayListener() または AChoreographer_registerRefreshRateCallback()

setFrameRate() を呼び出す際は、正確なフレームレートを渡すことをおすすめします。 数値を丸めるよりも効率的ですたとえば、100% の高頻度で録画された動画をレンダリングする場合、 29.97 Hz の場合は、30 に四捨五入するのではなく、29.97 を渡します。

動画アプリの場合は、setFrameRate() に渡される互換性パラメータを設定する必要があります 追加のヒントを Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE に指定できます。 一致しないものに適応するためにアプリがプルダウンを使用する Android プラットフォーム 表示のリフレッシュ レートを変更することもできます(この場合、揺れが生じます)。

状況によっては、動画のサーフェスでフレームの送信が停止するが、 画面に何も表示されません一般的なシナリオとしては ユーザーが再生を一時停止したときこのような場合 フレームレート パラメータを 0 に設定して setFrameRate() を呼び出し、サーフェスのクリア フレームレート設定をデフォルト値に戻しますフレームレートの設定を消去する 表面を破壊する場合や、表面が破損した場合に、 ユーザーが別のアプリに切り替えたため、非表示になります。フレームレートをクリアする 設定できるのは、サーフェスが使用されずに表示されている場合のみです。

非シームレス フレームレートの切り替え

デバイスによっては、リフレッシュ レートを切り替えると、画面が黒くなるなど、表示が途切れることがある 表示されます。これは通常、セットトップ ボックス、テレビパネル、 同様のデバイスが含まれますデフォルトでは、Android フレームワークはモードを切り替えません。 Surface.setFrameRate() のときに API が呼び出されるのは、このような視覚的な中断を避けるためです。

ユーザーによっては、ゲームの開始時に視覚的な中断を望み、 長い動画の終わりです。これにより、ディスプレイのリフレッシュ レートが 動画のフレームレートを改善し、3:2 のようなフレームレート変換のアーティファクトを回避します。 ムービー再生用のプルダウン ジャダー。

そのため、非シームレスのリフレッシュ レートの切り替えは、 ユーザーとアプリのオプトイン:

常に CHANGE_FRAME_RATE_ALWAYS を使用することをおすすめします。 長時間の動画視聴に適していますなぜなら、複数の単語を 動画のフレームレートは、動画の解像度の変更時に発生する中断を上回ります。 リフレッシュレートを指定できます

その他の推奨事項

一般的なシナリオでは、以下の推奨事項に従ってください。

複数のサーフェス

Android プラットフォームは、次のようなシナリオを適切に処理できるように設計されています。 フレームレート設定が異なる複数のサーフェスアプリに複数の フレームレートが異なるサーフェスの場合は、正しい値で setFrameRate() を呼び出します。 各サーフェスのフレームレートを指定します同じデバイスで複数のアプリを 分割画面モードやピクチャー イン ピクチャー モードを使用すると、 自分のサーフェス用の setFrameRate()

プラットフォームがアプリのフレームレートを変更しない

デバイスがサポートしている場合でも、呼び出しでアプリが指定するフレームレート setFrameRate()、デバイスのディスプレイが 更新頻度を指定しますたとえば、優先度の高いサーフェスは異なる デバイスがバッテリー セーバー モード( バッテリーを節約するためにディスプレイのリフレッシュ レートを制限するなど)。この状態でもアプリは リフレッシュ レートがデバイスによってディスプレイのリフレッシュ レートが デバイスが通常モードに切り替わっても、アプリのフレームレート設定 対応できます。

ディスプレイのリフレッシュ レートが変化したときの応答方法は、アプリによって決定されます アプリのフレームレートと一致していません。動画の場合、フレームレートは動画のフレームレートに 元の動画が表示され、動画コンテンツを表示するにはプルダウンが必要になります。 ゲームは代わりにディスプレイのリフレッシュ レートで実行しようとし、 望ましいフレームレートを維持しますアプリはその値を変更してはなりません。 プラットフォームの動作に基づいて setFrameRate() に渡されます。設定されたままになっているはずです。 アプリが優先されるフレームレートで応答します。これは、 アプリのリクエストに一致するようにプラットフォームが調整されることはありません。こうすれば、 追加のディスプレイ リフレッシュ レートを使用できるようにする場合は、 アプリの優先フレームに切り替えるための正しい情報がプラットフォームにあること 。

アプリがディスプレイのリフレッシュ レートで実行できない、または実行できない場合、アプリは 各フレームの表示タイムスタンプを指定します。 表示タイムスタンプを設定するプラットフォームのメカニズムは次のとおりです。

これらのタイムスタンプを使用すると、プラットフォームがアプリフレームを表示することもできなくなる 不要な揺れの原因になります。フレームの正しい使用方法 表示タイムスタンプは少し複雑です。ゲームについては、 フレーム ペーシング ガイド をご覧ください。また、 Android Frame Pacing ライブラリ

場合によっては、プラットフォームがアプリのフレームレートの倍数に切り替わる setFrameRate() で指定します。たとえば、アプリは setFrameRate() を呼び出します。 60 Hz で出力すると、ディスプレイが 120 Hz に切り替わることがあります。このことが 別のアプリのサーフェスでフレームレートが 24 Hz に設定されている場合に発生します。イン ディスプレイを 120Hz で実行すると、60Hz サーフェスと プルダウンなしで動作させる 24 Hz サーフェス。

ディスプレイがアプリのフレームレートの倍数で実行されている場合、アプリは 不要な表示を避けるため、各フレームの表示タイムスタンプを ジャダー。ゲームの場合、Android Frame Pacing ライブラリを使用すると、 設定しています。

setFrameRate() と preferredDisplayModeId の比較

WindowManager.LayoutParams.preferredDisplayModeId も、アプリがフレームレートをプラットフォームに示す方法です。一部 その他のアプリは、ディスプレイのリフレッシュ レートではなく、 表示モード設定(ディスプレイ解像度など)通常は preferredDisplayModeIdsetFrameRate() に変更。setFrameRate() 関数は、テキスト メッセージ全体を検索する必要がないため、簡単に使用できます。 表示モードのリストを使用して、特定のフレームレートのモードを検索できます。

setFrameRate() にすると、対応するプラットフォームをプラットフォームが選択できる機会が増えます。 複数のサーフェスが同時に実行されている場合、 使用することですたとえば、2 つのアプリが 2 つのインスタンスに Google Pixel 4 の分割画面モードで動作し、一方のアプリが 24 Hz の動画を再生している もう 1 つはスクロール可能なリストですGoogle Pixel 4 は ディスプレイのリフレッシュ レートは 60 Hz と 90 Hz です。preferredDisplayModeId API を使用すると、 動画サーフェスは 60Hz または 90Hz のいずれかを選択します。通話 setFrameRate() は 24 Hz で、動画サーフェスによってプラットフォームにもたらされます ソース動画のフレームレートに関する情報が 提供されます。これによりプラットフォームは ディスプレイのリフレッシュ レートには 90 Hz を選択します。この例では 60 Hz よりも優れています。 説明します。

ただし、preferredDisplayModeId を使用する必要があるシナリオもあります。 setFrameRate() ではなく、次のように入力します。

  • アプリで解像度やその他の表示モード設定を変更したい場合は、 preferredDisplayModeId を使用します。
  • プラットフォームは、呼び出しに応答してのみ表示モードを切り替えます。 モード切り替えが軽量で、その可能性が低い場合は setFrameRate() ユーザーの目に触れる場合もありますアプリでディスプレイの更新を切り替える場合 負荷の高いモードの切り替え(Android TV など)が必要な場合でも、 preferredDisplayModeId を使用します。
  • アプリの複数のフレームで実行されているディスプレイを処理できないアプリ (フレームごとに表示タイムスタンプを設定する必要がある)レートでは、 preferredDisplayModeId を使用します。

setFrameRate() と PreferredRefreshRate の比較

WindowManager.LayoutParams#preferredRefreshRate アプリ ウィンドウで優先フレームレートを設定し、そのレートが ウィンドウ内のすべてのサーフェスに設定できます。アプリは優先ルールを フレームレートはデバイスがサポートするリフレッシュ レートは問いません。 setFrameRate(): アプリの意図をスケジューラが把握しやすくするために、 あります。

setFrameRate() を使用するサーフェスでは、preferredRefreshRate は無視されます。イン 可能であれば、通常は setFrameRate() を使用してください。

PreferredRefreshRate と PreferredDisplayModeId

アプリで優先リフレッシュ レートのみを変更する場合は、 preferredDisplayModeId ではなく preferredRefreshRate

setFrameRate() を頻繁に呼び出すのを避ける

setFrameRate() の呼び出しは、パフォーマンスの点でそれほど費用はかかりませんが、 アプリでフレームごとに、または 1 フレームごとに複数回 setFrameRate() を呼び出さないようにする必要がある なります。setFrameRate() を呼び出すと、 画面の切り替え時にフレーム落ちが発生する可能性があります。 事前に適切なフレームレートを把握しておき、 setFrameRate() を 1 回。

ゲームやその他の動画以外のアプリでの使用

動画は setFrameRate() API の主なユースケースですが、 使用しないでください。たとえば、次の値よりも高く実行しないことを意図したゲームは、 60 Hz の場合(消費電力を減らし、再生時間を伸ばすため)は、 Surface.setFrameRate(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT)。この デフォルトで 90 Hz で動作するデバイスは 60 Hz で動作し、 ゲームがアクティブになり、 ゲームは 60 Hz で実行され、ディスプレイは 90 Hz で実行されました。

FRAME_RATE_COMPATIBILITY_FIXED_SOURCE の使用

FRAME_RATE_COMPATIBILITY_FIXED_SOURCE は動画アプリ専用です。対象 動画以外での使用の場合は、FRAME_RATE_COMPATIBILITY_DEFAULT を使用します。

フレームレートの変更方法を選択する

  • 長時間の動画を表示する場合は、アプリの 映画、呼び出し setFrameRate(fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS) ここで、fps は動画のフレームレートです。
  • CHANGE_FRAME_RATE_ALWAYS を使用して setFrameRate() を呼び出すアプリは強くおすすめしません 動画再生の継続時間が数分以下と予想されるとき。

動画再生アプリの統合例

動画再生アプリにリフレッシュ レートの切り替えを統合するには、次の手順をおすすめします。

  1. changeFrameRateStrategy を決定します。 <ph type="x-smartling-placeholder">
      </ph>
    1. 映画などの長時間実行動画を再生する場合は、MATCH_CONTENT_FRAMERATE_ALWAYS を使用します。
    2. 予告編などの短い動画を再生する場合は、CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS を使用します。
  2. changeFrameRateStrategyCHANGE_FRAME_RATE_ONLY_IF_SEAMLESS の場合 手順 4 に進みます。
  3. 次のチェック ボックスをチェックして、非シームレスのリフレッシュ レートの切り替えが行われようとしているかどうかを検出する 次の両方の事実が正しいことを確認する必要があります。 <ph type="x-smartling-placeholder">
      </ph>
    1. 現在のリフレッシュ レートからシームレス モードに切り替えることはできません( C)を動画のフレームレート(V と呼ぶ)にマッピングします。これにより、 C と V が異なっていて Display.getMode().getAlternativeRefreshRates V の倍数は含まれません。
    2. ユーザーが、シームレスではないリフレッシュ レートの変更を有効にしている。新しい P-MAX キャンペーンを これを確認するには、DisplayManager.getMatchContentFrameRateUserPreference は、MATCH_CONTENT_FRAMERATE_ALWAYS を返します。
  4. 切り替えをシームレスに行う場合は、次の手順を行います。 <ph type="x-smartling-placeholder">
      </ph>
    1. setFrameRate を呼び出す fpsFRAME_RATE_COMPATIBILITY_FIXED_SOURCEchangeFrameRateStrategyfps は動画のフレームレート)です。
    2. 動画の再生を開始
  5. 非シームレス モードの変更が行われる場合は、次の手順を行います。 <ph type="x-smartling-placeholder">
      </ph>
    1. ユーザーに通知する UX を表示します。なお、Terraform でインフラストラクチャを ユーザーにこの UX を閉じて、ステップ 5.d の追加の遅延をスキップするよう促します。これは、 遅延が推奨されるディスプレイでは 必要な時間より長いためです スイッチング時間が短縮されます
    2. setFrameRate を呼び出す fpsFRAME_RATE_COMPATIBILITY_FIXED_SOURCE、 および CHANGE_FRAME_RATE_ALWAYS、 ここで、fps は動画のフレームレートです。
    3. onDisplayChanged を待ちます。 呼び出すことができます。
    4. モードの切り替えが完了するまで 2 秒ほど待ちます。
    5. 動画の再生を開始

シームレス切り替えのみをサポートする疑似コードは次のとおりです。

SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
transaction.setFrameRate(surfaceControl,
    contentFrameRate,
    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
    CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
transaction.apply();
beginPlayback();

上記のようなシームレス切り替えと非シームレス切り替えをサポートする擬似コードは次のとおりです。

SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
if (isSeamlessSwitch(contentFrameRate)) {
  transaction.setFrameRate(surfaceControl,
      contentFrameRate,
      FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
      CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
  transaction.apply();
  beginPlayback();
} else if (displayManager.getMatchContentFrameRateUserPreference()
      == MATCH_CONTENT_FRAMERATE_ALWAYS) {
  showRefreshRateSwitchUI();
  sleep(shortDelaySoUserSeesUi);
  displayManager.registerDisplayListener();
  transaction.setFrameRate(surfaceControl,
      contentFrameRate,
      FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
      CHANGE_FRAME_RATE_ALWAYS);
  transaction.apply();
  waitForOnDisplayChanged();
  sleep(twoSeconds);
  hideRefreshRateSwitchUI();
  beginPlayback();
}