質問で述べたように、MPlayer が UDP ストリームを再生できない理由は 2 つ (実際には 3 つ) ありました。
最初の理由は、パケット化に関係しています。NVEnc は、その出力バッファーを NALU と呼ばれるデータ ブロックで満たします。NALU は、主にビットストリーム同期を目的とした「開始コード」で区切ります。(Annex Bとその競合他社AVCCについて詳しく知りたい場合は、 szatmaryの優れたSO回答にアクセスしてください)。
現在の問題は、NVEnc が 1 つの出力バッファーで複数の NALU を配信することがあるということです。ほとんどの NALU にはエンコードされたビデオ フレームが含まれていますが、解像度やフレームレートなどのメタデータも送信する必要がある場合があります (ストリームの開始時に必須です)。そのさらに下)。
ただし、プレーヤー ソフトウェアは、単一の UDP パケットで複数の NALU を取得することをサポートしていません。これは、開始コード (2 つまたは 3 つの「0」バイトの後に「1」バイトが続く) を探す単純なループをプログラムして、出力バッファーを分割し、各 NALU を独自の UDP パケットで送信する必要があることを意味します。(ただし、UDP パケットにはこれらの開始コードが含まれている必要があることに注意してください。)
パケット化に関するもう 1 つの問題は、IP パケットが一般的に特定のサイズを超えることができないことです。繰り返しになりますが、SO の回答は、さまざまなコンテキストでのこれらの制限についての貴重な洞察を提供します。ここで重要なことは、これを自分で処理する必要はありませんが、エンコーダ オブジェクトの作成時に次のパラメータを設定して、NVEnc にその出力を「スライス」するように指示する必要があるということです。
m_stEncodeConfig.encodeCodecConfig.h264Config.sliceMode = 1;
m_stEncodeConfig.encodeCodecConfig.h264Config.sliceModeData = 1500 - 28;
(m_stEncodeConfig
は に渡されるパラメータ構造体でありNvEncInitializeEncoder()
、1500 はイーサネット パケットの MTU であり、28 は IP4 ヘッダーと UDP ヘッダーの追加サイズです)。
MPlayer がストリームを再生できなかった 2 つ目の理由は、ビデオをファイルに保存するのではなく、ストリーミング ビデオの性質に関係しています。プレーヤー ソフトウェアが H.264 ファイルの再生を開始すると、解像度、フレームレートなどを含む必要なメタデータ NALU が検出され、その情報が保存されるため、二度と必要なくなります。一方、ストリームを再生するように要求された場合、そのストリームの先頭を見逃しており、送信者がメタデータを再送信するまで再生を開始できません。
ここに問題があります。別段の指示がない限り、NVEnc はエンコード セッションの最初の段階でのみメタデータ NALU を生成します。設定する必要があるエンコーダ構成パラメータは次のとおりです。
m_stEncodeConfig.encodeCodecConfig.h264Config.repeatSPSPPS = 1;
これは、NVEnc に SPS/PPS NALU を時々再生成するように指示します (デフォルトでは、これはすべての IDR フレームを意味すると思います)。
そしてほら!これらのハードルがクリアされると、CPU にほとんど負荷をかけずに、圧縮されたビデオ ストリームを生成する能力を理解できるようになります。
編集: この種の超単純な UDP ストリーミングは、実際にはどの標準にも準拠していないため、お勧めできません。Mplayer はそのようなストリームを再生しますが、それ以外の場合はほとんど何でも再生できる VLC は再生できません。一番の理由は、送信されるメディアのタイプ (この場合はビデオ) を示すデータ ストリームが何もないことです。私は現在、受け入れられている基準を満たす最も簡単な方法を見つけるために研究を行っています。