FFmpeg が RTSP によってプッシュされた H265 ストリームを再生するときにエラーが報告される問題を解決する

1. 背景の紹介

RTSP (Real Time Streaming Protocol) は、リアルタイム ストリーミング プロトコルであり、TCP/IP プロトコル システムのアプリケーション層プロトコルです。

RTP (リアルタイム トランスポート プロトコル) は、トランスポート層に位置するネットワーク伝送プロトコルですが、通常は UDP プロトコルの最上位で実行されます。

昨年、私は RTSP を使用して H265 コード ストリームをプッシュし、表示のためにプルすることについて 2 つの記事を書きました。HEVC コード ストリームの RTSP プッシュと表示を実現しHEVC コード ストリームをエンコードしたい場合は、ビデオ画面が表示されます前者は、RTSP+RTP を使用してローカル H265 コード ストリームをプッシュし、VLC ソフトウェアを使用してストリームをプルして表示します。後者は x265 エンコーダーを使用し、エンコード プロセス中に RTSP+RTP を使用してストリームをプッシュおよび表示します。

ビデオを録画し、RTSP を使用してローカル H265 ビデオをプッシュし、次に VLC ソフトウェアを使用して表示用のストリームをプルしました。その効果は次のとおりです。

、再生時間 00:39

しかし、現在のほとんどのビデオ プレーヤー (ストリーミング メディアを含む) がFFmpeg フレームワークに基づいていることは誰もが知っているでしょう。より具体的には、それらは FFplay カーネルに基づいています。たとえば、ステーション B のijkplayerオープン ソース プロジェクトも FFplay に基づいており、モバイル端末に適したカプセル化と最適化。

したがって、H265 ストリームを正常にプルして表示するには VLC ソフトウェアを使用するだけでは十分ではなく、FFmpeg の FFplay ツールを使用して RTSP によってプッシュされた H265 ストリームをプルして再生および表示するのが最善です。

しかし、このテストを実行すると、次のエラーが発生しました。

報告される主なエラーは次のとおりです。

RTP/HEVCパケット内の不正な一時 ID

しかし、奇妙なことに、コード ストリームの同じ RTSP アドレスに対して、VLC ソフトウェアを使用してネットワーク上でストリーミングすると、再生されるビデオは正常であるということです。

今日は、FFplay がプルして再生できないというこの小さなバグを解決してみましょう。

2. 問題箇所

インターネットで検索しましたが、インターネット全体 (Google 検索の使用を含む) で見つかった唯一の関連する議論は次のとおりです。

でもそれは私には何の役にも立たないような気がするのに、なぜそんなことを言うのですか?

テストに使用したFFplayはFFmpeg公式サイトからダウンロードしたRelease版exeファイルです。再生側で FFplay のソースコードを変更するのは現実的ではありませんし、FFplay もエラーを報告するため独自のロジックやルールがあるため、その判定を強制的に削除するのは無理がありますただし、上記のようにストリーミング側でIDフィールドに値を割り当てる方法を試すことができます。では、このエラー レポートの ID は何でしょうか?

[学習アドレス]: FFmpeg/WebRTC/RTMP/NDK/Android オーディオおよびビデオ ストリーミングの高度な開発
[記事の特典]: より多くのオーディオおよびビデオ学習教材パッケージ、主要メーカーからのインタビュー質問、技術ビデオ、および学習ロードマップを無料で受け取ります。 (C/C++、Linux、FFmpeg webRTC rtmp hls rtsp ffplay srs など) 必要な場合は、 1079654574をクリックして グループに参加して取得できます~

実際、私が初めて一時 ID を見たとき、 H265 の nuh_temporal_id_plus1 (NALU ヘッダー) に関連しているのではないかと大まかに推測しました。

これが本当にそうなのかどうかについては、FFmpeg のソース コードで追跡する必要がありますが、「RTP/HEVC パケット内の一時 ID が不正です」というエラー メッセージを出力する背後にあるコード ロジックは何ですか?

まず、FFmpeg公式サイトまたはGithubからソースコードをダウンロードする必要がありますが、FFmpegのソースコードをSource Insightソフトウェアに追加したので、このソフトウェア内で「RTP/HEVCパケット内の不正な一時ID」を直接検索することができ、結果は次のとおりです。

つまり、rtpdec_hevc.cファイルの 185 行目のhevc_handle_packet関数にこの出力があります。もっとよく見なさい、

FFmpeg ソース コードが RTP にカプセル化された H265 コード ストリームを解析するときに、tid 値が 0 であると判断すると、「RTP/HEVC パケット内の一時 ID が不正です」というエラー メッセージが出力されることがわかります。

では、ここでの tid の値は何でしょうか?

    nal_type =  (buf[0] >> 1) & 0x3f;    lid  = ((buf[0] << 5) & 0x20) | ((buf[1] >> 3) & 0x1f);    tid  =   buf[1] & 0x07;

FFmpeg コード内の buf[0] と buf[1] は、実際には、H265 コード ストリームの NALU ヘッダーの 2 バイトに対応します。buf[1]&0x07 プロセスは、NALU ヘッダーの 2 番目のバイトの下位 3 ビット値を取得します。これは、上で推測した nuh_temporal_id_plus1 構文要素の値です

FFmpeg のソース コードでnuh_temporal_id_plus1 が 0 にならないことを確認する必要があるのはなぜですか?

答えは、ITU-T の H265 ホワイト ペーパーにあります。

つまり、H265 規格ではこの値を 0 にすることはできないと明確に規定されているため、FFmpeg のソース コードによるチェックは合理的で問題ありません。したがって、インターネットで見つかった解決策は、クライアントの判断を削除すると言っていますが、これは明らかに間違ったアプローチですそのため、インターネット上に公開されている情報は玉石混交ですので、皆さんも慎重に確認してください。

戻ってもう一度考えてみましょう。ローカル H265 コード ストリーム ファイルが RTSP サーバーにプッシュされるとき、RTP カプセル化プロセスを受ける必要があります。FFmpeg は、プッシュした RTP パッケージの nuh_temporal_id_plus1 値に問題があることを検出したため、2 つの疑いがあります。

ローカル H265 コード ストリーム自体の NALU ヘッダーに問題があるか、RTP カプセル化の実行時に問題があります

テストに使用したH265コードストリームについて、NALUヘッダーの値が0かどうかは、コードストリーム解析ソフトを使用することで確認できます。結果は以下の通りです。

明らかに、この H265 コード ストリーム ファイルの NALUHeader のnuh_temporal_id_plus1値は0 ではなく 1 です。

この場合、RTP が H265 コード ストリームをカプセル化する場合にのみ問題が発生する可能性があります。

3. 問題解決

RTP でビデオをカプセル化する原理を理解できたでしょうか? 実際、RTP で H265 ネイキッド ストリームをカプセル化するプロセスは比較的単純です。RTP プロトコルのヘッダーは 12 バイトで、ネイキッド ストリーム H265 が RTP ペイロードとして使用されます。RTP ペイロードとしての H265 ネイキッド フローの特定のルールについては、次の標準を参照してください。

https://www.rfc-editor.org/rfc/pdfrfc/rfc7798.txt.pdf

H265 コード ストリームの RTP カプセル化について学習した後、次に独自の RTSP プッシュ H265 ビデオ テキスト コードを確認します。最後に、 H265Source.cppファイルの HandleFrame 関数にロジックの問題があることが判明しました

RTP プロトコルが H265 ビデオをカプセル化し、各 NALU データを取得する場合、受信する正式パラメータの Frame_buf および Frame_size には、実際には NALU スタート コード データと長さが含まれます。rfc7798 標準によれば、RTP が H265 コード ストリームをカプセル化する場合、次の図の右側に示すように、スタート コードをスキップする必要があります。

上の図は、RTP パケットに NALU を入力する様子を示していますが、NALU の実際のデータ長が最大値 MAX_RTP_PAYLOAD_SIZE (ここで定義されているのは 1420 バイト) を超える場合は、図のように開始コードもスキップする必要があります。次の図で:

スタート コードがスキップされない場合、H265 コード ストリームのスタート コード (0x00 00 00 01) の 2 バイト目の値は 0 でなければならないため、frame_buf[1] によって取得される NALU ヘッダーの tid 値は 0 になります。コードを修正した後、最終的に FFplay を再度使用して RTSP の H265 コード ストリームを取得した結果は次のとおりです。

、再生時間 00:37

コード変更後、FFplay ソフトウェアを使用して RTSP によってプッシュされたローカル H265 ビデオを再生できることがわかりますが、VLC ソフトウェアよりも少し遅く感じます (最初のビデオを比較してください)。

上のビデオでは、FFplay がストリーミングしているときにスクリプト ffplay_rtsp.bat が実行され、その内容は次のとおりです。

.\ffplay.exe -window_title codec2022_test -x 1280 -y 720 -rtsp_transport tcp "rtsp://127.0.0.1:554/codec2021"

このうち、-window_title codec2022_test は FFplay 再生ウィンドウ名 codec2022_test を指定することを意味し、-x 1280 -y 720 は FFplay プレーヤー ウィンドウの解像度を指定することを意味します。rtsp://127.0.0.1:554/codec2021 は、私が自分で設定した RTSP コード ストリーム アドレスです。

4. まとめ

上記は、FFplay がディスプレイをプルし、RTSP を使用してローカル H265 ビデオ エラーをプッシュする問題を解決するために使用したプロセスです。問題を分析し、ソース コードを詳しく調査した結果、最終的に FFplay を使用して H265 ビデオをストリーミングおよび表示することに成功しました。お役に立てば幸いです。

元のリンク: FFmpeg が RTSP によってプッシュされた H265 コード ストリームを再生するときのエラー報告の問題を解決する

おすすめ

転載: blog.csdn.net/irainsa/article/details/129846364