問題タブ [nvenc]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
opengl - nvEncRegisterResource() が -23 で失敗する
NVEnc を使用して OpenGL フレームを H264 としてストリーミングしようとして、完全なレンガの壁にぶつかりました。私はこの特定の問題に8時間近く取り組んできましたが、何の進展もありませんでした。
問題は への呼び出しnvEncRegisterResource()
です。コード -23 で必ず失敗します (enum 値 NV_ENC_ERR_RESOURCE_REGISTER_FAILED、「リソースの登録に失敗しました」と記載されています - NVidia に感謝します)。
私はオスロ大学のこのドキュメント(54 ページ、「OpenGL 相互運用」) で概説されている手順に従おうとしているので、残念ながらこのドキュメントではコード自体が提供されていませんが、これが機能するはずであるという事実を知っています。 .
アイデアはかなり単純です。
- OpenGL フレーム バッファ オブジェクトによって生成されたテクスチャを CUDA にマップします。
- テクスチャを (以前に割り当てられた) CUDA バッファにコピーします。
- そのバッファを NVEnc 入力リソースとしてマップします
- その入力リソースをエンコードのソースとして使用します
私が言ったように、問題はステップ(3)です。関連するコード スニペットを次に示します (簡潔にするために、エラー処理は省略しています)。
これにより、デバイス上の CUDA メモリが割り当てられるはずです (「ピッチ付き」の種類ですが、ピッチなしも試しましたが、結果は変わりません)。
これがレンガの壁です。何をしようとしても、nvEncRegisterResource()
失敗します。
私は、必要な初期化をすべて行ったと考えています (間違っているかもしれませんが)。CUDA コンテキストを作成してアクティブ化するコードは次のとおりです。
.. エンコーディング セッションの作成が続きます。
最後に、エンコーダーを初期化するコード:
上記の初期化はすべて成功を報告します。
このハードルを乗り越えてくれる人には本当に感謝しています。
編集:問題を再現するための完全なコードは次のとおりです。元のコードとの唯一の違いは、cuPopContext()
ここでエラー (無視できます) を返すことです。おそらく、私の元のプログラムは、OpenGL を使用することの副作用として、このようなコンテキストを作成します。それ以外の場合、コードは元のコードとまったく同じように動作します。Visual Studio 2013 でコードをビルドしました。次のライブラリ ファイルをリンクする必要があります (C: でない場合はパスを調整します)。C:\Program Files (x86)\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\Win32\cuda.lib
C:\Program Files (x86)\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include\
また、 (または類似の) がインクルード パスにあることを確認する必要があります。
新しい編集: ランタイム API と混合する代わりに、CUDA ドライバー インターフェイスのみを使用するようにコードを変更しました。それでも同じエラーコードです。
video - NVidia NVEnc ハードウェア エンコーダを使用して UDP 経由で H.264 ビデオをストリーミングする方法は?
これは自己回答型の質問になるでしょう。なぜなら、丸 1 週間にわたって私は気が狂ってしまったからです。私が経験したフラストレーションを仲間のプログラマーに惜しみなく与えたいと思っています。
状況は次のとおりです: NVidia の NVEnc ハードウェア エンコーダー (Kepler および Maxwell カード、つまりそれぞれ GT(x) 7xx および GT(x) 9xx で使用可能) を使用して、グラフィックス アプリケーションの出力を UDP 経由でストリーミングしたいと考えています。これは取るに足らない方法ではありませんが、NVEnc にはビデオ メモリに直接アクセスする機能があるため、エンコーディング ステージの後まで、ビデオ メモリからシステム メモリにフレームを「ダウンロード」する必要がなくなるため、非常に効率的です。
NVEncの出力バッファをフレームごとに書き込むだけで.h264ファイルを生成する限り、私はすでにこの作業を行うことができました。VLC は、タイミングがずれていたことを除いて、そのようなファイルの再生に問題はありませんでした (デバッグ目的でのみそのファイルが必要だったので、これを修正しようとしませんでした)。
エンコードされたフレームを UDP 経由でストリーミングしようとしたときに問題が発生しました。VLC も MPlayer もビデオをレンダリングできませんでした。それには 2 つの理由があることがわかりました。これについては、私の回答で説明します。
ffmpeg - ffmpeg nvenc GPU メモリ使用量
Ubuntu のNVIDIA QUADRO K4200でビデオをトランスコードしています( ffmpeg バージョンは 2.7.1、NVENC SDK 5.0.1 です)。1 つのストリームの GPU メモリ使用量は 100 MB です。nvidia-smi コマンドの出力を参照してください。
しかし、 NVIDIA GTX 980 TI ( ffmpeg バージョンは 3.0、NVENC SDK 5.0.1) を搭載した別のコンピューターで同じ ffmpeg パラメーターを使用して同じトランスコーディング プロセスを実行すると、 1 つのストリームの GPU メモリ使用量は 170 MB になります。以下のスクリーンショットをご覧ください。
なぜメモリ使用量にこのような違いがあるのでしょうか? QUADRO K4000 のように、GTX 980 TI の GPU メモリ使用量を 1 回のトランスコード プロセスで 100MB に減らすことはできますか?
opengl - 計算段階と CUDA によるデータ アクセスの間でメモリ バリアが同期に失敗する
次のパイプラインがあります。
- カスタム FBO へのテクスチャ アタッチメントにレンダリングします。
- そのテクスチャ アタッチメントをイメージとしてバインドします。
- imageLoad/Store を使用して、上記の画像からコンピューティング シェーダー サンプリングを実行します。
- 結果を SSBO またはイメージに書き込みます。
- SSBO (または画像) を CUDA CUgraphicsResourceとしてマップし、CUDAを使用してそのバッファーからのデータを処理します。
さて、問題はステージ 4 と 5 の間のデータの同期にあります。私が試した同期ソリューションは次のとおりです。
glFlush - すべてのコマンドの実行の完全性を保証しないため、実際には機能しません。
glFinish - これは機能します。ただし、ドライバーに送信されたすべてのコマンドをファイナライズするため、お勧めしません。
ARB_sync ここでは、パフォーマンスに大きく影響するため、推奨されないと言われています。
glMemoryBarrierこれは興味深いものです。しかし、それは単に機能しません。
コードの例を次に示します。
また、試しました:
コードの実行は次のようになります。
さらに、計算を起動する前にコンテキストから FBO とテクスチャのバインドを解除しようとしglMemoryBarrier
ました。それらの間にセットを置いて次々と計算を起動し、最初の計算起動からターゲット イメージを CUDA にフェッチすることさえ試みました。まだ同期していません。(まあ、2 つの計算が互いに同期していないので、これは理にかなっています)
計算シェーダー段階の後。同期しない!glFinish
、またはパイプラインを完全に失速させる他の操作に置き換えた場合のみ。glMapBuffer()
たとえば、のように。
それでは、glFinish() を使用する必要がありますか、それともここに何かが欠けていますか? CUDA が制御を引き継ぐ前に glMemoryBarrier() が計算シェーダーの動作を同期しないのはなぜですか?
アップデート
元の質問がかなり古いので、質問を少しリファクタリングしたいと思います。それにもかかわらず、最新の CUDA および Video Codec SDK (NVENC) を使用しても問題は解決していglMemoryBarrier
ません。したがって、同期しない理由は気にしません。私が知りたいのは:
レンダリング パイプライン全体 (私の場合は OpenGL イメージ) を停止することなく、OpenGL コンピューティング シェーダーの実行を CUDA の共有リソースの使用と同期させることができる場合。
答えが「はい」の場合、どのように?
ffmpeg - NVENC コーデックを使用した 60 fps での FFmpeg によるデスクトップ グラビング
最新の Windows でコンパイルされた FFmpeg と NVENC コーデックを使用してデスクトップを 60FPS で記録するのに問題があります。メタデータによると、ファイルは 60 fps ですが、再生すると 60 FPS ではないことがはっきりとわかります。
私が使用するコマンドラインは次のとおりです。
リアルタイム バッファを使用したり、別の DirectShow デバイスを使用したり、プロファイルを変更したり、ビットレートを強制したりしてみましたが、ビデオは常に 30fps のようです。
NVIDIA の ShadowPlay を使用した画面の記録はうまく機能するので、私のマシンで実行可能であることはわかっています。
FFprobe を使用して ShadowPlay の出力ファイルを確認すると、次のことがわかります。
ストリーム #0:0(und): ビデオ: h264 (高) (avc1 / 0x31637661), yuv420p(tv, smpte170m/smpte170m/bt470m), 1920x1080 [SAR 1:1 DAR 16:9], 4573 kb/s, 59.38 fps、240 tbr、60k tbn、120 tbc (デフォルト)
しかし、出力に同じビットレートとプロファイルを強制すると、次のようになります。
ストリーム #0:0(und): ビデオ: h264 (高) (avc1 / 0x31637661)、yuv420p、1920x1080 [SAR 1:1 DAR 16:9]、5519 kb/s、60 fps、60 tbr、15360 tbn、120 tbc (デフォルト)
私は見ることができ、異なっtbr
てtbn
いるので、出力がフレームを複製していることがわかります。
テストのために、すべての録画の背景にこの 60 フレーム レートのテスト ページがあり、違いがはっきりとわかりました。
ShadowPlay はおそらく、同じコーデックを使用する FFmpeg よりも内部で多くのことを行うことを知っています。OBS で簡単に実行できることはわかっていますが、何が間違っているのかを理解したいと思います。多分それはFFmpegの制限ですか?
完全なコンソール出力
-v trace コマンドの使用:
c++ - HVEC を使用した Nvidia NvEnc により Div by Zero が発生する
Nvidias NvEnc API を使用してハードウェア エンコーダーを構築しようとしています。この API は、任意のデータをエンコードするために、H264 と HEVC の 2 つのコーデックを使用します。したがって、最初に 2 つのコードのいずれかを選択し、その後、エンコード セッションを構成するか、さまざまなプリセットのいずれかを使用する必要があります。Nvidias NvEnc Programming Guideで説明されているようにやっています。
HVECコーデックを使用しているときに問題を引き起こす次のコードがあります:
繰り返しになりますが、私は H264 GUID を使用しており、すべてが実行されます。HEVC を使用すると、Div by Zero が表示されます... API 呼び出しからエラー コードが表示されず、単純な div by zero エラーが表示されます。私の質問は次のとおりです: HEVC には、プリセットを使用して提供していない情報が必要ですか? もしそうなら、どのような情報ですか?
どうもありがとう!
編集:解決しました。プログラミング ガイドには、これらのフィールドを設定する必要があるとは記載されていませんでしたが、NV_ENC_INITIALIZE_PARAMSはframeRateNumとframeRateDenで構成されているため、div がゼロになりました... H264 を使用しているときにこれが発生しない理由はわかりません。誰かがこれを閉じるかもしれません..
nvenc - nvencで最もビジーでないGPUを見つける方法は?
C プロジェクトで nvenc lib を使用して複数の GPU をサポートする作業を行っています。最も使用率の低い GPU を見つけて、次のエンコーダ セッションに使用したいと思います。それを行うためのAPIはありますか?
ありがとう。
codec - NVENC SDK の例
ハードウェア アクセラレーション ビデオ エンコーディングを提供できる NVENC エンコーダー SDK サンプルを実行しようとしています。
nvencoder
ここで見つけたデータセットでサンプルを実行しようとしています: http://www.sunrayimage.com/download/image_examples/yuv420/tulips_yuv420_inter_planar_qcif.yuv
次のコマンドラインで実行しました。
生成された結果のファイルは、実際にはどのメディア プレーヤーでも再生できません。VLC はそれをロードしますが、期待していたイメージを生成しません。
ヘルプ メッセージを見ると、次のように書かれています。
このファイルが再生可能であることを確認するために他に何かする必要があるのでしょうか、それともこの例を正しく使用していないのでしょうか? ビットストリーム ファイルが有効な H.264 エンコード ファイルではない可能性がありますか?