web-dev-qa-db-ja.com

MBのデコード中のffmpeg RTSPエラー

私はffmpegを使用して、Cisco 3050 IPカメラからh264 RTSPストリームを読み取り、h264としてディスクに再エンコードします(-codec:copyだけを使用していない理由があります)。

Ffmpegのバージョンは次のとおりです。

ffmpeg version 3.2.6 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 6.3.0 (Alpine 6.3.0)

私はまた、ffmpeg 2.8.14-0ubuntu0.16.04.1とソースからビルドされた最新のffmpeg(私は this commitを使用しました)を試してみましたが、以下と同じ動作が見られます。

私が実行しているコマンドは次のとおりです。

ffmpeg -rtsp_transport udp -i 'rtsp://<user>:<pw>@<ip>:554/StreamingSetting?version=1.0&action=getRTSPStream&ChannelID=1&ChannelName=Channel1' -r 10 -c:v h264 -crf 23 -x264-params keyint=60:min-keyint=60 -an -f ssegment -segment_time 60 -strftime 1 /output/%Y%m%d_%H%M%S.ts -abort_on empty_output

毎秒少なくとも1つのかなり安定した速度でさまざまなエラーが発生します。これがサンプルです:

[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets
[h264 @ 0x55b1e115d400] left block unavailable for requested intra mode
[h264 @ 0x55b1e115d400] error while decoding MB 0 12, bytestream 114567
[h264 @ 0x55b1e115d400] concealing 3889 DC, 3889 AC, 3889 MV errors in I frame

最も一般的なのは「MB x x、バイトストリームxのデコード中のエラー」です。これは、再生時のビデオファイルの深刻な破損に対応します。

Stackoverflowやその他の場所でそのエラーメッセージへの多くの参照が表示されますが、満足のいく説明や回避策はまだ見つけていません。これは、ストリームの最後の欠落データに対応するように見える この行 から来ています。 「利用できない左のブロック」は here から来ており、欠落データのようにも見えます。

他の人は代わりに-rtsp_transport tcpを使用することを提案しています( 12 、)これは私の場合、わずかに異なるエラーの組み合わせを与えるだけです、そしてまだビデオの破損:

[h264 @ 0x557923191b00] left block unavailable for requested intra4x4 mode -1
[h264 @ 0x557923191b00] error while decoding MB 0 28, bytestream 31068
[h264 @ 0x557923191b00] concealing 2609 DC, 2609 AC, 2609 MV errors in I frame
[rtsp @ 0x7f88e817b220] CSeq 5 expected, 0 received.

Wiresharkを使用して、UDPとTCP=モードの両方で、すべてのパケットがカメラからPCに送信されていることを確認しました(順次RTPシーケンス番号なし行方不明)ffmpegに到着した後、データが失われていると思います。

Panasonic WV-SFV110カメラに対して同じコマンドを実行したときにも同様の動作が見られますが、全体的にエラーの発生頻度は低くなっています。パナソニックのカメラでUDPからTCP=に切り替えると、エラー/破損が減少しますが、完全になくなるわけではありません。

私もVLCで同様のコマンドを試し、同様のエラー(cvlc rtsp://<user>:<pw>@<ip>/MediaInput/h264 :sout='#transcode{vcodec=h264}:std{access=file, mux=ts, dst="output.ts"})を取得しました-おそらくlibavがffmpegから分岐したため、コードはあまり分岐していません。

カメラはPCのPoEポートに直接接続されるので、ネットワークの輻輳は問題になりません。 PCにライブストリームのエンコードを維持するのに十分なCPUがある場合、ffmpegの問題で、TCPストリームからデータがまだドロップされることが問題です。

定性的に、問題を悪化させると思われるいくつかの要因があります:

  • より高いビデオ解像度
  • Ffmpegを実行しているマシンのシステム負荷が高い(例:低解像度の.aviファイルへのトランスコーディングは、h264 VBRへのトランスコーディングよりもエラーが少ない。-codec:copyを使用すると、ffmpegの起動中のカップル以外のすべてのエラーが解消される)
  • カメラビュー内の動きが大きい

エラーはどういう意味ですか?そして、私はそれについて何ができますか?

7
Hugh W

パケット損失が問題のように聞こえます。ビデオ解像度が高く、動きが大きいほど、エンコードされたビデオストリームのビットレートが増加し、パケット損失が増加します。失われたパケットに応じて、投稿で示したように、デコードプロセスでさまざまなエラーが表示されます。

Ffmpegを実行するシステム負荷が高いことは、ネットワークカードがパケットをドロップしている可能性があることも示しています。 ffmpegは、ビデオのトランスコーディングでビジー状態のときに、それらを読み取るのに時間がかかりすぎます。

最初の質問はあなたのネットワークトポロジーは何ですか?公衆インターネットを介したストリーミングは、LANを介したストリーミングよりもはるかに困難です。ネットワークにはどのようなスイッチ/ルーターがありますか?

次の質問、カメラはどのビットレートでストリーミングしていますか?これを減らして結果を確認してください。あなたのアプローチで体系的である、すなわち。

  • 最初はトランスコードしないでください。
  • ビデオを受け取るだけです。
  • ファイルに書き込みます。
  • パケット損失/ビデオアーティファクトを確認します。
  • より低いビットレートで開始します。 100kbpsで、損失が明らかでない場合はこれを増やします

次に行うことは、レシーバーバッファーのサイズを増やすことです。私はffmpegにあまり詳しくありませんが、 ここ のように_recv_buffer_size_で設定できるようです。次に、カメラの構成に基づいて、保存するのに十分な大きさを計算する必要があります。数秒(5?)のビデオデータ。レシーバーバッファーのサイズを増やすときにアーティファクトが少なくなるか、またはアーティファクトのない期間が長くなるかを確認します。

もちろん、プロセッサが遅すぎてリアルタイムでビデオをトランスコードできない場合は、遅かれ早かれスペースが足りなくなります。その場合は、より低い解像度/ビットレートにトランスコードするか、それほど集中的でないエンコーダ設定を使用する必要があるかもしれません。または、より高速なマシンでトランスコーディングを実行します。

また、レシーバーバッファーのサイズを調整しても、公共のインターネットで発生するパケット損失は補償されないため、上記はカメラのビットレートをサポートするローカルネットワークでストリーミングしていると想定するのに役立ちます。ネットワークの帯域幅を超えると、パケット損失が発生する可能性があります。その場合、TCP=を介したストリーミングは、(少なくとも受信バッファが最終的にオーバーランするまで)ある程度は役立つ可能性があります)。

上記の方法で問題が完全に解決しない場合は、次のことを試してください。

  • 着信トラフィックをwiresharkまたはtcpdumpで盗聴します。痕跡を見てください。 「RTSP」を使用してトレースをフィルタリングします。 RTPトラフィックが連続しているRTPパケットには、20、21、22、23などのシーケンス番号の増加があります。シーケンス番号を入力すると、パケット損失が発生し、TCPを介してストリーミングを試みます。TCPを介してストリーミングしながらトレースを繰り返します。また、TCPを介してストリーミングする場合も、レシーバーのバッファーサイズを増やすことを忘れないでください。

要約すると、パイプラインアーキテクチャがあり、パイプラインのどこで損失が発生しているかを判断する必要があります。

camera -> network -> receiver buffer (OS) -> application (ffmpeg)

5
Ralf

最初のエラーメッセージを見てください。

[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets

UDPパケットを失っていると思います。 H.264エラーメッセージの残りの部分は、不完全なビットストリームを受信したことが原因です。ここで重要なのは、問題を特定することです。ネットワークはパケットをドロップしていますか?または、UDP(RTP)を受信するサーバーの速度が遅すぎるか、過負荷になっていますか。

まず、OSのUDPバッファサイズを確認します。 https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/jgroups-perf-udpbuffer.html

UDPバッファーサイズを大きくしても効果がない場合は、ffmpegを-codec:copyと一緒に使用してCPUの負荷を下げます。それでもエラーが発生しますか?再エンコードする場合は、Intel Quicksync -vcodec h264_qsvまたは他のハードウェアエンコーダーを使用してCPUの負荷を下げることを検討してください。

PCに十分なCPUがあるかどうかは問題ではありません。しかし、処理パイプラインでボトルネックを特定することについての詳細。 H.264エンコーダー(x264)がCPUをオーバーサブスクライブする可能性があるため、瞬間的なピーク負荷が発生してパケットがドロップします。 x264のスレッド数を制限するか、品質を「高速」または「高速」に下げてください。

5
Markus Schumann