1
GOP設定がIntel H264ハードウェアMFTで受け入れられない
問題文: IntelハードウェアMFTはGOP設定を順守していないため、リアルタイムアプリケーションでより多くの帯域幅が消費されます。同じコードがNvidiaハードウェアMFTで正常に機能します。 バックグラウンド: 私は、Windows10マシンでMediaFoundation H264ハードウェアエンコーダーを使用して、DesktopDuplication APIを通じてキャプチャされたNV12サンプルをビデオストリームにエンコードし、LAN上でリアルタイムにストリーミングおよびレンダリングしようとしています。 エンコーダーは出力サンプルを配信する前に最大25フレーム(GOPサイズ)をバッファリングしていたため、最初はエンコーダーでの過度のバッファリングに直面していました。いくつかの調査の結果、CODECAPI_AVLowLatencyModeを設定すると待ち時間が短縮され、品質と帯域幅が少し低下することがわかりました。 CODECAPI_AVLowLatencyModeプロパティを設定すると、パフォーマンスは少し向上しましたが、リアルタイムの要件には達しませんでした。エンコーダーは、少なくともサンプルを生成する前に最大15フレームをバッファリングするように見えます(出力に約2秒の遅延が導入されています)。また、この動作は、低いフレームレートが構成されている場合にのみ顕著になります。60FPSでは、出力はほぼリアルタイムで、視覚的に目立つ遅延はありません。 実際、フレームレートが30FPS未満に設定されている場合にのみ、バッファリングが人間の目で認識されます。また、遅延はFPS構成に反比例して増加します。25FPSでの遅延は数百ミリ秒であり、FPSが10(一定レート)に構成されている場合は最大3秒になります。おそらく、FPSを30(60FPSなど)より大きく設定すると、エンコーダバッファがすぐにオーバーフローして、目立たない遅延のサンプルが生成されると思います。 最近、CODECAPI_AVEncCommonRealTimeプロパティ(https://docs.microsoft.com/en-us/windows/win32/directshow/avenccommonrealtime-property)を試して、帯域幅の消費を避けるために入力フレームレートを下げるときにパフォーマンスが向上するかどうかを確認しましたただし、その呼び出しは「パラメーターが正しくありません」エラーで失敗し ます。 私の実験: 一定のフレームレートを維持し、エンコーダーにリアルタイム出力を生成させるために、同じサンプル(以前に保存されたサンプル)を30FPS / 60FPSの一定のレートでエンコーダーに供給しています。私はこれを最大10FPS(または必要な任意のFPS)でのみキャプチャし、同じサンプルを3回またはEMULATED_FRAME_RATE / ACTUAL_FRAME_RATE比に基づいたレートで正確に供給して30 / 60FPSを偽造することでこれを行っています(例:30 / 10、60 / 15 、60/20)一定の間隔でギャップを正確に埋めます。たとえば、10秒間変化がない場合、同じサンプルを30 * 10回(30FPS)エンコーダーに供給しました。このアプローチについては、いくつかのオープンソースGithubプロジェクトから、またchromiumの実験的なコードサンプルからも学びました。また、私は知らされていました(主にSO、 また、他のフォーラムでは、これがリアルタイム出力のためにエンコーダーをプッシュする唯一の方法であり、それを回避する方法はありません。 上記のアプローチはほぼリアルタイムの出力を生成しますが、以前に保存したサンプルのみをエンコーダーに供給している場合でも、予想よりも多くのデータを消費します。 出力ビットレートは、Intel MFTでは常に350KBpsから500KBpsの範囲にとどまり、NVidia MFT(30FPSおよび500KBビットレート構成)では80KBpsから400KBpsの間で変化します。画面のコンテンツが30FPSで変化するか0FPS(アイドル)で変化するかは関係ありません。この場合、NVidiaハードウェアエンコーダの方がいくらか優れているようです。 実際、画面のアイドル時間中に、エンコーダーは前述の速度よりも毎秒多くのデータを生成していました。より大きなGOPサイズを設定することで、 NVidiaデバイスのデータ消費を削減できました(現在のGOPサイズは16Kです)。ただし、画面のアイドル時のデータ消費量はIntelグラフィックス620ハードウェアでは約300KBps、NVidia GTX 1070(構成:500KBビットレートおよび30FPS)では50KBps〜80KBpsのままですが、これは許容できません。おそらく、インテルのハードウェアMFTはGOP設定をまったく順守していないか、改善が目立ちません。 また、非常に低いビットレートを設定することで、IntelとNvidiaのハードウェアでアイドル時間のデータ消費をそれぞれ〜130KBpsと〜40KBpsに下げることもできましたが、これも許容できないため、ビデオ品質も低下します。 入力サンプル間で変更が発生しなかった場合に、最大10KBps未満の出力を生成するようにエンコーダーを構成する方法はありますか?変更が発生しない場合、私は実際には〜0KBの出力を目指していますが、〜10KBpsはある程度許容可能です。 更新: 私は、以下に、いくつかのパラメータを微調整することにより、NVidiaのMFTのアイドルタイムデータの消費量をダウンさせることができるよ400キロバイトのビットレート設定で〜20kbpsの、そして以下の100キロバイトのビットレート設定で〜10KBps。これは説得力があります。ただし、同じコードで同じエンコーダ構成を使用すると、Intelマシンでは20〜40倍のデータが生成されます。インテル(インテルグラフィックス620)はGOP設定を順守していません。私はGOPを256からINT_MAXの間で変化させてみましたが、IntelハードウェアMFTの出力では何も変化していないようです。 アップデート2: エンコーダープロパティで遊んだ後(eAVEncCommonRateControlMode_CBRの代わりにeAVEncCommonRateControlMode_UnconstrainedVBRでCODECAPI_AVEncCommonRateControlModeを構成しただけです)、画面のアイドル時にインテルMFTが3KBpsデータを生成することがわかりましたが、最初の数秒間だけ(おそらく約3〜8秒) 、それから同じ話に戻ります。数秒後、エンコーダはサンプルと比較するキーフレームへの参照を失い、その時点以降は回復していないようです。GOPが16/128/256/512/1024でもINT_MAXでも、動作は同じです。 エンコーダ構成: リファレンス:http : //alax.info/blog/1586 const int EMULATED_FRAME_RATE = …