詳細: VideoNG

Dale Curtis
Dale Curtis

Chromium のメディア再生のエンジニアリング リード、Dale Curtis と申します。私のチームは、動画再生用のウェブ向け API(MSEWebCodecs など)と、音声と動画のデマルチプレックス、デコード、レンダリングに関連するプラットフォーム固有の内部処理を担当しています。

この記事では、Chromium の動画レンダリング アーキテクチャについて説明します。拡張機能に関する詳細の一部は Chromium 固有のものですが、ここで説明するコンセプトと設計のほとんどは、他のレンダリング エンジンやネイティブ再生アプリにも適用されます。

Chromium の再生アーキテクチャは、長年にわたって大きく変化してきました。このシリーズの最初の投稿で説明した成功のピラミッドの考え方から始めることはありませんでしたが、最終的には信頼性、パフォーマンス、拡張性という同様の手順に沿って作業を進めました。

当初、動画レンダリングは非常にシンプルでした。コンポジタに送信する動画フレームをデコードするソフトウェアを選択する単なる for ループでした。長年にわたり、これは十分に信頼できるものでしたが、ウェブの複雑さが増すにつれて、パフォーマンスと効率性の向上が必要となり、アーキテクチャが変更されました。多くの改善には OS 固有のプリミティブが必要でした。そのため、Chromium のすべてのプラットフォームに対応できるように、アーキテクチャを拡張する必要もありました。

さまざまな Chromium プラットフォームへのレンダリング フローの図。

動画のレンダリングは、配信する内容の選択と、その情報を効率的に配信する 2 つのステップに分けることができます。読みやすさを考慮して、Chromium が配信内容を選択する方法に入る前に、効率的な配信について説明します。

用語とレイアウト

この記事ではレンダリングに焦点を当てているため、パイプラインのデマルチプレクシングとデコードについては簡単に説明します。

受信バイトと送信構造化パケット。

セキュリティを重視する現代において、デコードとデマルチプレックスには十分な注意が必要です。バイナリ パーサーはリッチなターゲット環境であり、メディア再生にはバイナリ パーサーが大量に使用されます。そのため、メディア パーサーのセキュリティ問題は非常によく発生します。

Chromium では、ユーザーに対するセキュリティ問題のリスクを軽減するために、多層防御を実践しています。具体的には、デマルチプレクシングとソフトウェア デコードは常に低権限プロセスで行われ、ハードウェア デコードはシステムの GPU と通信するのに十分な権限を持つプロセスで行われることを意味します。

レンダラ、GPU、音声処理のプロセス用の Chromium サンドボックス。

Chromium のクロスプロセス通信メカニズムは Mojo と呼ばれます。この記事では Mojo の詳細については説明しません。Mojo はプロセス間の抽象化レイヤとして、Chromium の拡張可能なメディア パイプラインの基盤となっています。再生パイプラインを説明する際には、このことを念頭に置いてください。これは、メディアの受信、デマルチプレックス、デコード、最終的な表示のために相互作用するクロスプロセス コンポーネントの複雑なオーケストレーションに影響します。

ビット数が多い

最新の動画レンダリング パイプラインを理解するには、動画が特別である理由(帯域幅)を理解する必要があります。60 フレーム/秒で 3840x2160(4K)解像度の再生では、9 ~ 12 Gbps のメモリ帯域幅を使用します。最新のシステムではピーク帯域幅が数百ギガビット / 秒に達することもあります。それでも、動画再生は依然として大きな部分を占めています。注意しないと、GPU メモリと CPU メモリ間のコピーや移動により、合計帯域幅が簡単に増加する可能性があります。

効率性を重視した最新の動画再生エンジンの目標は、デコーダと最終的なレンダリング ステップ間の帯域幅を最小限に抑えることです。このため、動画のレンダリングは Chromium のメイン レンダリング パイプラインから大部分が分離されています。具体的には、メインのレンダリング パイプラインの観点から、動画は不透明度のある固定サイズの穴にすぎません。Chromium では、サーフェスというコンセプトを使用してこれを実現しています。これにより、各動画が Viz に直接通信します。

穴と「動画をここに配置」という矢印があるウェブページ。

モバイル コンピューティングの普及に伴い、電力と効率が現在の世代の重要な焦点となっています。その結果、デコードとレンダリングがハードウェア レベルでかつてないほど連携し、OS 自体でも動画が不透明な穴のように見えるようになります。多くの場合、プラットフォーム レベルのデコーダは、Chromium がオーバーレイの形でプラットフォーム レベルの合成システムに渡す不透明バッファのみを提供します。

穴と「動画をここに配置」という矢印のあるウェブページが、オペレーティング システムを表すボックスで囲まれている。

どのプラットフォームにも、プラットフォームのデコード API と連携する独自のオーバーレイがあります。Windows には Direct CompositionMedia Foundation Transforms があり、macOS には CoreAnimation LayersVideoToolbox があり、Android には SurfaceViewMediaCodec があり、Linux には VASurfacesVA-API があります。これらのコンセプトの Chromium の抽象化は、それぞれ OverlayProcessor インターフェースと mojo::VideoDecoder インターフェースによって処理されます。

これらのバッファをシステム メモリにマッピングできる場合、不透明である必要はなく、アクセスされるまで帯域幅を消費しません。Chromium では、これを GpuMemoryBuffers と呼びます。Windows では DXGI バッファ、macOS では IOSurfaces、Android では AHardwareBuffers、Linux では DMA バッファがバッファの基盤となります。通常、動画の再生ではこのアクセスは必要ありませんが、これらのバッファは、キャプチャ デバイスと最終的なエンコーダ間の帯域幅を最小限に抑えるために、動画キャプチャにとって重要です。

前述のバッファの図。

多くの場合、GPU はデコードと表示の両方を担当するため、これらの(多くの場合)不透明バッファを使用すると、高帯域幅の動画データが実際に GPU から出力されることがなくなります。前述のように、データを GPU に保持することは、特に高解像度とフレームレートで効率を高めるために非常に重要です。

オーバーレイや GPU バッファなどの OS プリミティブを活用できるほど、不要な動画バイトのシャッフルに費やす帯域幅が少なくなります。デコードからレンダリングまですべてを 1 か所で行うことで、驚異的な電力効率を実現できます。たとえば、macOS で Chromium のオーバーレイを有効にすると、全画面動画の再生中の消費電力が半減しました。WindowsAndroidChromeOS などの他のプラットフォームでは、フルスクリーン以外のケースでもオーバーレイを使用できるため、ほぼすべての場所で最大 50% の節電が可能です。

レンダリング

最適な配信メカニズムについて説明したので、Chromium が配信内容を選択する方法について説明します。Chromium の再生スタックは「プル」ベースのアーキテクチャを使用します。つまり、スタック内の各コンポーネントは、階層順に下位のコンポーネントから入力をリクエストします。スタックの上部には音声フレームと動画フレームのレンダリングがあり、その下にはデコード、デマルチプレックス、最後に I/O があります。レンダリングされた各音声フレームは、プレゼンテーション間隔と組み合わせてレンダリングする動画フレームの選択に使用されるクロックを進みます。

各表示間隔(ディスプレイの各更新)で、動画レンダラは、前述の SurfaceLayer に接続された CompositorFrameSink によって動画フレームの提供を求められ、フレームレートがディスプレイ レートより低いコンテンツの場合、同じフレームが複数回表示されます。フレームレートがディスプレイ レートより高い場合、一部のフレームは表示されません。

視聴者に心地よく見えるように音声と映像を同期するには、他にも多くの方法があります。Chromium で最適な動画のスムーズさを実現する方法について詳しくは、Project Butter をご覧ください。動画レンダリングを、各フレームを表示する回数を表す理想的なシーケンスに分割する方法について説明します。たとえば、「表示間隔ごとに 1 フレーム([1]、60 Hz で 60 fps)」、「2 つの間隔ごとに 1 フレーム([2]、60 Hz で 30 fps)」、または複数の異なるフレームと表示間隔をカバーする [2:3:2:3:2](60 Hz で 25 fps)などの複雑なパターンがあります。動画レンダラがこの理想的なパターンに近づくほど、ユーザーは再生がスムーズだと感じやすくなります。

デマルチプレックス、デコード、レンダリングの順序。

ほとんどの Chromium プラットフォームはフレームごとにレンダリングしますが、すべてではありません。拡張可能なアーキテクチャでは、バッチ処理されたレンダリングも可能です。バッチ処理レンダリングは、OS レベルのコンポジタに複数のフレームについて事前に通知し、アプリが指定したタイミング スケジュールでそれらのリリースを処理する効率的な手法です。

未来はすでに始まっている?

Chromium が OS プリミティブを活用してクラス最高の再生エクスペリエンスを提供する方法に重点を置いています。では、基本的な動画再生を超える機能を提供したいウェブサイトの場合はどうすればよいでしょうか。Chromium 自体が次世代のウェブ コンテンツを実現するために使用しているのと同じ強力なプリミティブを、クリエイターにも提供できるでしょうか?

答えは「イエス」です。 拡張性は、Google がウェブ プラットフォームについて考える際の中心的な考え方です。Google は、他のブラウザやデベロッパーと連携して WebGPUWebCodecs などの新しいテクノロジーを開発してきました。これにより、ウェブ デベロッパーは、Chromium が OS とやり取りするときに使用するプリミティブをそのまま使用できます。WebGPU は GPU バッファをサポートし、WebCodecs は前述のオーバーレイと GPU バッファ システムと互換性のあるプラットフォームのデコードとエンコードのプリミティブを導入します。

WebCodecs と WebGPU の関係。

ライブ配信の終了

最後までお読みいただきありがとうございました。最新の再生システムと、Chromium が毎日数億時間の総再生時間を支える仕組みについて、理解を深めていただければ幸いです。コーデックと最新のウェブ動画について詳しくは、Sid Bala の H.264 is magic、Erica Beaves の How Modern Video Players Work、Cyril Concolato の Packaging award-winning shows with award-winning technology をご覧ください。

Una Kravets によるイラスト(かわいいやつです)。