H.264 FU-A RTP 断片化の修正: RTSP ビデオが壊れる理由 (パケット損失、NAL 再構成)
H.264 FU-A RTP フラグメンテーションによる壊れた RTSP ビデオを修正します。フラグメントの欠落、開始/終了ビットのバグ、NAL 再構成の失敗、パケット損失、MTU、およびデコーダ エラーを実際の診断コマンドでカバーします。
H.264 over RTP はデコーダのバグのように見えますが、実際にはパケット化の問題です。 RTSP セッションは機能します。 DESCRIBE は有効な SDP を返します。セットアップは成功します。 PLAY は 200 OK を返します。 RTP パケットは、H.264 にマッピングされた正しいペイロード タイプで到着します。それでも、ビデオにはブロックの破損、フリーズ、ブラック フレーム、またはデコーダ エラーが表示されます。
ログではエラーは次のようになります。
[h264 @ 0x...] invalid NAL unit size
[h264 @ 0x...] missing picture in access unit
[h264 @ 0x...] non-existing PPS 0 referenced
[h264 @ 0x...] decode_slice_header error
[h264 @ 0x...] no frame!
The fast answer
Why fragmentation exists
The structure of an FU-A packet
Each FU-A RTP packet contains:
Byte 0: FU indicator
bit 7: F (forbidden_zero_bit) — normally 0
bits 6-5: NRI (nal_ref_idc) — priority
bits 4-0: Type = 28 (FU-A)
Byte 1: FU header
bit 7: S (Start) — 1 for first fragment
bit 6: E (End) — 1 for last fragment
bit 5: R (Reserved) — always 0
bits 4-0: Type — original NAL unit type (1=non-IDR, 5=IDR, 7=SPS, 8=PPS)
Byte 2+: Fragment payload — the actual NAL unit data
1 つの NAL ユニットの完全な FU-A シーケンス:
Packet 1: FU indicator (type=28) | FU header (S=1, E=0, type=5) | payload[0..N]
Packet 2: FU indicator (type=28) | FU header (S=0, E=0, type=5) | payload[N+1..M]
Packet 3: FU indicator (type=28) | FU header (S=0, E=0, type=5) | payload[M+1..P]
Packet 4: FU indicator (type=28) | FU header (S=0, E=1, type=5) | payload[P+1..END]
The RTP marker bit
Failure modes: what breaks and why
Failure 1: Missing middle fragment
Expected: 1000(S) 1001(M) 1002(M) 1003(E|marker)
Received: 1000(S) 1001(M) [LOST] 1003(E|marker)
リアセンブラーは開始フラグメント、1 つの中間フラグメント、次に終了フラグメントを認識しますが、ペイロード バイトは接続されません。再組み立てされた NAL ユニットには隙間があります。
症状:
- フレームの横帯のブロック破損
- デコーダが「無効な NAL ユニット サイズ」を報告する
- 破損は 1 つのアクセス ユニットに限定されます (次の IDR で解消されます)
失敗 2: 開始フラグメントの欠落
Expected: 1000(S) 1001(M) 1002(E)
Received: [LOST] 1001(M) 1002(E)
Failure 3: Missing end fragment
Expected: 1000(S) 1001(M) 1002(E|marker)
Received: 1000(S) 1001(M) [LOST]
再アセンブラーは最後のフラグメントを決して認識しません。 NAL ユニットの境界は決して確認されません。デコーダは、到着しないさらなるデータを待ちます。
症状:
- ビデオがフリーズする
- デコーダーが「アクセス ユニットに画像がありません」と報告する
- 次の完全なアクセス ユニットが到着するまで再生が停止します
失敗 4: フラグメントの順序が乱れている
Expected: 1000(S) 1001(M) 1002(E)
Received: 1000(S) 1002(E) 1001(M)
Diagnostic workflow
Step 1: Confirm H.264 payload mapping
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=4D0029;sprop-parameter-sets=...
- 「packetization-mode=1」は非インターリーブモードを意味します(FU-Aがサポートされています)
- 「packetization-mode=0」はシングル NAL ユニット モードを意味します (断片化なし - 非常に限定的)
ステップ 2: RTP シーケンス番号を追跡する
キャプチャで、ビデオ トラックの RTP シーケンス番号を確認します。ギャップはパケット損失を示します。
Seq 1000: FU-A Start, NAL type 5 (IDR)
Seq 1001: FU-A middle
Seq 1003: FU-A End, marker=1 ← gap at 1002
Step 3: Inspect FU-A headers
Byte 0 (FU indicator):
0x7C = NRI=3, Type=28 (FU-A)
バイト 1 (FU ヘッダー):
0x85 = S=1、E=0、R=0、Type=5 (IDR スライス) ← IDR の開始フラグメント
0x45 = S=0、E=0、R=0、Type=5 ← 中央のフラグメント
0x65 = S=0、E=1、R=0、Type=5 ← 終了フラグメント。この NAL がアクセスユニット末尾の場合だけマーカーを設定
探す値が間違っています:
- 非開始パケットの S=1 → 再アセンブラの混乱
- E=1 より前にマーカーを設定 → 誤ったアクセスユニット境界
- E=1 でも後続 NAL がある場合は、マーカー未設定が正しいことがあります
- シーケンス途中でタイプが変更される → エンコーダーのバグまたはストリームの破損
ステップ 4: 完全に再組み立てされたことを確認する
各 NAL ユニットについて:
- 開始フラグメントを見つけます (S=1)
- 最後のフラグメント (E=1) まで連続するシーケンス番号をたどります。
- フラグメントを数えます。配列ギャップがないことを確認する
- マーカーをアクセスユニット境界と照合し、すべての FU-A 終了フラグメントには要求しません。
- すべてのフラグメントのタイムスタンプと NAL タイプが同じであることを確認します。
ステップ 5: トランスポート モードを比較する
UDP と TCP をインターリーブして同じストリームを実行します。 TCP ではビデオが正常でも、UDP では破損している場合、問題はエンコーダやデコーダの問題ではなく、ネットワーク パケット損失です。
ステップ 6: IDR と非 IDR の分析
IDR フレームはより大きく、NAL ユニットごとにより多くの FU-A フラグメントを必要とします。フラグメントが多い = パケット損失の危険性が高くなります。破損が主にシーンの変更時または数秒ごと (IDR 間隔で) に発生する場合、IDR フレームが被害者になります。
修正オプション:
- IDR フレーム サイズを小さくします (キーフレームの解像度またはビットレートを下げます)。
- IDR 間隔を長くします (大きなフレームは少なくなりますが、損失からの回復が遅くなります)
- エンコーダーでの FU-A の MTU を削減します (フラグメントは増えますが、それぞれのフラグメントが小さくなり、IP フラグメンテーションが引き起こされる可能性が低くなります)。
回復戦略
再アセンブラーで
- 部分的なデータをデコーダに供給するのではなく、損傷したアクセスユニットを完全に削除します
- RTCP 経由で新しい IDR フレームをリクエストします (カメラでサポートされている場合)
- 次の IDR フレームを待ちます (デコーダは自動的に回復します)。
エンコーダで
- NAL ユニット サイズ制限を下げて、アクセス ユニットあたりのフラグメントを削減します。
- 完全な IDR フレーム (小さいキーフレーム) の代わりに定期的なイントラリフレッシュを使用します。
- RTP スタックがサポートしている場合、FEC (前方誤り訂正) を有効にします。
ネットワークで
- パケット損失が避けられない場合は、UDP から TCP インターリーブに切り替える
- パス MTU 検出が機能することを確認します (IP フラグメンテーションを回避します)。
- 混雑したリンク上の RTP トラフィックを優先する
FU-Aではないとき
すべての H.264 破損が FU-A 断片化であるわけではありません。チェック:
- SPS/PPS が欠落しています: 「存在しない PPS」などのデコーダ エラー — SDP sprop-parameter-sets を確認してください
- 間違ったプロファイル/レベル: デコーダーはストリームの複雑さを処理できません
- エンコーダのバグ: エンコーダは無効な NAL ユニット構文を生成します
- ソースのビットストリーム破損: ネットワークではなく、カメラのエンコーダが壊れています
RTP パケットが完全なシーケンス番号と正しい FU-A ヘッダーで到着してもデコーダが失敗する場合、問題はトランスポートではなく H.264 ビットストリーム自体にあります。
<!-- rtsp-localized-evidence-foundation-v1:start -->「H.264 FU-A RTP 断片化の修正: RTSP ビデオが壊れる理由 (パケット損失、NAL 再構成)」を再現可能に検証する手順
結論から言うと、黒画面や一つのステータスコードだけでは障害の所在を証明できません。信頼できる診断では、RTSP の要求と応答、合意した Transport、有効な Session、その後の RTP シーケンス番号、タイムスタンプ、RTCP の証拠を一つの時系列につなげます。「H.264 FU-A RTP 断片化の修正: RTSP ビデオが壊れる理由 (パケット損失、NAL 再構成)」では表示症状に近い層から調べますが、制御、ネットワーク、デコーダーの問題を混同しないよう同じ記録時刻を使います。
カメラ、ファイアウォール、VMS の設定を変える前に、小さな基準テストを作ります。パスワードを除いた RTSP URL、時刻、パス、要求した Transport、サーバー応答、最初のメディアパケット到着時刻を記録してください。機器が対応する場合は UDP と TCP interleaved を別々に試します。パス、認証情報、Transport を同時に変えると、二回目の成功がどの変更によるものか分かりません。
| 確認層 | 保存する証拠 | 判断する質問 |
|---|---|---|
| RTSP | メソッド、状態、ヘッダー、CSeq、Session | サーバーはその操作を受理したか |
| SDP | control、payload type、clock rate、codec | 期待するトラックが記述されているか |
| Transport | client_port、server_port、interleaved | 両端が同じ経路を使うか |
| RTP | SSRC、sequence、timestamp、marker | メディア単位が説明可能な順序で届くか |
| RTCP | sender report、CNAME、BYE | 時計、識別子、終了を追跡できるか |
| Decoder | SPS/PPS/VPS、packetization mode | 受信 payload で初期化できるか |
「メディアが届かない」と「届くが復号できない」を分けます。SETUP と PLAY が成功しても RTP がなければ、UDP 経路、NAT、ファイアウォール、Transport 応答を調べます。シーケンスの穴は損失または並べ替えを示します。連続した RTP があるのに映像がなければ、payload type、clock rate、フレーム境界、H.264 または H.265 のパラメーターへ進みます。この境界はプレーヤーの一般的なエラーより有用です。
引用できる短い回答はどう書きますか
三文で、最後に成功した操作、最初に失敗した証拠、二つの原因を分ける次の試験を書きます。例は「DESCRIBE、SETUP、PLAY は成功した。通知されたクライアントポートに RTP が届かない。TCP interleaved の再試験で UDP 遮断とメディアパス誤りを分ける」です。応答やパケットなしにカメラやネットワーク全体を原因と断定しません。
再現に必要な最小情報は何ですか
OPTIONS、DESCRIBE、SETUP、PLAY、SDP、Transport 応答、秘密を除いた Session を保存します。RTP は SSRC、最初と最後のシーケンス、clock rate、欠落数、収録時間を記録します。VLC や別 VMS の成否は差分試験として有用ですが、成功したクライアントが全規則を正しく扱う証明ではありません。
サーバーとクライアントのどちらを調べますか
メソッド拒否、存在しない control URL、不一致 Transport、説明のない SSRC や時計変更はサーバー側を調べます。期限切れ nonce の再利用、Session 欠落、ポートを開かない UDP 要求、各 NAL 終端を access unit 終端とみなす処理はクライアント側を調べます。中間経路の問題では、各結論にパケットと時刻を添えます。
報告前に何を確認しますか
新しい接続で再試験し、二つの時系列を最初の相違点まで比較します。パスワードと完全な Authorization 値を削除し、結論を CSeq、sequence、timestamp に結び付けます。関連する RTSP ガイドで周辺手順を確認し、RTSP Inspectorで RTSP ストリームをローカルに試験してください。カメラ映像を公開サービスへアップロードする必要はありません。
<!-- rtsp-localized-evidence-foundation-v1:end -->