17
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ffmpeg でファイルから4K HEVC疑似ライブストリーミング (その2 リベンジ編)

Posted at

こんにちは、先日人生初屋形船に乗って興奮を隠しきれない streampack の木村です。

前回の記事 ffmpeg でファイルから4K HEVC疑似ライブストリーミング で映像品質が安定しなかったので、その原因を探るべく調査しました。

ちなみに画面が乱れたときはこんな状態です。

Screenshot_20180516-144907_ExoPlayer.jpg

症状からみてパケット落ちだろうーなー

UDP パケットロスの痕跡

netstat -su および  Wowza エラーログ から UDP のパケロスが発生していることが確認できます。

ffmpeg 側

$ netstat -su
IcmpMsg:
    InType3: 12
Udp:
    553 packets received
    0 packets to unknown port received.
    0 packet receive errors
    3505549 packets sent
UdpLite:
IpExt:
    InOctets: 938459
    OutOctets: 4705709500
    InNoECTPkts: 12881

Wowza 側

$ netstat -su
IcmpMsg:
    OutType3: 12
Udp:
    3511272 packets received
    140 packets to unknown port received.
    3461 packet receive errors
    9961 packets sent
    RcvbufErrors: 3461
UdpLite:
IpExt:
    InOctets: 4754674233
    OutOctets: 3982940345
    InNoECTPkts: 4360851

Wowza のエラーログ

こんな感じでビデオフレーム欠落のメッセージが多数表示されます

WARN    server  comment 2018-05-17      13:32:54        -       -       -       -       -       244.771 -       -       -       -       -       -       -       -       RTPDePacketizerMPEGTS[live/_definst_/4Kdash.stream]: RTPDePacketizerMPEGTS.flushVideoBuffer: Video frame incomplete, dropping[250213:0:false]: 5346000
WARN    server  comment 2018-05-17      13:32:54        -       -       -       -       -       245.301 -       -       -       -       -       -       -       -       RTPDePacketizerMPEGTS[live/_definst_/4Kdash.stream]: RTPDePacketizerMPEGTS.flushVideoBuffer: Video frame incomplete, dropping[200173:0:false]: 5394000
WARN    server  comment 2018-05-17      13:33:44        -       -       -       -       -       294.763 -       -       -       -       -       -       -       -       RTPDePacketizerMPEGTS[live/_definst_/4Kdash.stream]: RTPDePacketizerMPEGTS.flushVideoBuffer: Video frame incomplete, dropping[264749:0:false]: 9846000
WARN    server  comment 2018-05-17      13:33:48        -       -       -       -       -       299.132 -       -       -       -       -       -       -       -       RTPDePacketizerMPEGTS[live/_definst_/4Kdash.stream]: RTPDePacketizerMPEGTS.flushVideoBuffer: Video frame incomplete, dropping[185453:0:false]: 10239000
WARN    server  comment 2018-05-17      13:33:53        -       -       -       -       -       303.972 -       -       -       -       -       -       -       -       RTPDePacketizerMPEGTS[live/_definst_/4Kdash.stream]: RTPDePacketizerMPEGTS.flushVideoBuffer: Video frame incomplete, dropping[186557:0:false]: 10674000

うにゃー、パケロスが起こっていることはわかったけど、送信側、受信側、ネットワーク、アプリ、どこ起因なのか判断つかず。
まず送信側が怪しいと踏んで、ffmpeg から調査します。

ffmpeg 側

ffmpeg の方で StreamingGuide が用意されており、パケットロスについて記載があるので、これらを順に試してみました。

対策1 pthreads

udp パケットロスが出るようであれば、pthreads が有効かどうか確認しろ! と書いているので確認したところ、そんなもんは有効になっていなかったので、ffmpeg を再コンパイルしました。

PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --extra-cflags="-I$HOME/ffmpeg_build/include" --extra-ldflags="-L$HOME/ffmpeg_build/lib" --bindir="$HOME/bin" --pkg-config-flags="--static" --enable-gpl --enable-nonfree --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-openssl --enable-pthreads --extra-libs=-lpthread

ここでまた ブッパマったのですが、それはまた別のお話で・・・

とりあえず再インスールしました。 これで大丈夫かな?

$ ffmpeg
ffmpeg version N-91085-ge351882 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-11)
  configuration: --prefix=/home/kimura/ffmpeg_build --extra-cflags=-I/home/kimura/ffmpeg_build/include --extra-ldflags=-L/home/kimura/ffmpeg_build/lib --bindir=/home/kimura/bin --pkg-config-flags=--static --enable-gpl --enable-nonfree --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-openssl --enable-pthreads --extra-libs=-lpthread

結果

流してみるとダメでした。

対策2 fifo_size=10000

ffmpeg で流す時に fifo_size=10000 を付けろ!とあるので付けてみます

ffmpeg -re -stream_loop -1 -i hevcuhd.mp4 -vcodec copy -acodec copy -flags +loop-global_header -f mpegts "udp://{Wowza IP Address}:6000?pkt_size=1316&fifo_size=10000"

結果

流してみるとダメでした。

対策3 buffer_size=10000000

バッファ上げろ! とあるので &buffer_size=10000000 を付けてみます

ffmpeg -re -stream_loop -1 -i hevcuhd.mp4 -vcodec copy -acodec copy -flags +loop-global_header -flush_packets 0 -f mpegts "udp://{Wowza IP Address}:6000?pkt_size=1316&buffer_size=10000000&fifo_size=10000"

結果

流してみるとダメでした。
パラメータの順番変えたりしてもダメでした。

Wowza 側

なになに? datagramMaximumPacketSize_in8192 にしろと?
仰せのままに・・・

/usr/local/WowzaStreamingEngine/conf/VHost.xml
<DatagramConfiguration>
    <Incoming>
        <ReuseAddress>true</ReuseAddress>
        <ReceiveBufferSize>2048000</ReceiveBufferSize>
        <SendBufferSize>65000</SendBufferSize>
        <!-- <MulticastBindToAddress>true</MulticastBindToAddress> -->
        <!-- <MulticastInterfaceAddress>[ip-address]</MulticastInterfaceAddress> -->
        <!-- <TrafficClass>0</TrafficClass> -->
        <MulticastTimeout>50</MulticastTimeout>
        <DatagramMaximumPacketSize>8192</DatagramMaximumPacketSize>
    </Incoming>
    <Outgoing>
        ...
    </Outgoing>
</DatagramConfiguration>

結果

流してみるとダメでした。

EC2 インスタンスタイプ変更

書いてませんでしたが、ffmpeg も Wowza も普段は t2.small で動かしています。
配信時のリソース状況を見ても負荷はほとんどかかっていない状況ですが、念のためにスケールアップしてみます。

エイヤ!!! 両方共 c4.xlarge でどうだ!

Image uploaded from iOS (3).jpg

結果

流してみるとダメでした。

ああーもうどうしたらええんじゃいっ!!

#そしてふと思い出す・・・

もしかしたら 10Mbps のビットレート送出に UDP 送受信バッファが低すぎるんじゃねーの??
そういえばだいぶ昔に Linux カーネルパラメーター弄って調整した案件があったなあ・・・

ってことで UDP 関連の送受信バッファの項目を弄ります。

Linux カーネル パラメーター変更

まず EC2 Amazon Linux の現在の設定値を確認してみます。

変更前

$ sudo sysctl -a |grep "net.core.*mem_*"
net.core.optmem_max = 20480
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_default = 212992
net.core.wmem_max = 212992

これを以下のコマンドで送受信バッファのデフォルトと MAX の設定値を 16MB に変更し、ffmpeg 側、Wowza 側の両方に適用します。

$ sudo sysctl -w net.core.rmem_default=16777216
$ sudo sysctl -w net.core.wmem_default=16777216
$ sudo sysctl -w net.core.rmem_max=16777216
$ sudo sysctl -w net.core.wmem_max=16777216

変更後

$ sudo sysctl -a |grep "net.core.*mem_*"
net.core.optmem_max = 20480
net.core.rmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_default = 16777216
net.core.wmem_max = 16777216

注:上記は変更は TCP 通信にも適用され、TCP/UDP ソケットを利用する他のサービス/アプリケーションにも影響を与えますので、十分にご注意下さい。
また、sysctl コマンドでの設定変更は一時的な変更ですので、OS 再起動すると元に戻ります。 恒久的に適用するには /etc/sysctl.conf に書き込みます。

結果

流してみるとダメじゃありませんでした!!

お金かかるので ffmpeg 側、Wowza 側共に t2.small に戻して 40分位回しましたが、映像の乱れもなく、パケロスも起きておりません。

Wowza 側

# netstat -su
Udp:
    1480023 packets received
    0 packets to unknown port received.
    0 packet receive errors
    389 packets sent
UdpLite:
IpExt:
    InOctets: 2000575930
    OutOctets: 1814875998

高画質、高品質ですわー

Screenshot_20180516-145832_ExoPlayer.jpg

調子に乗ってコンテンツを 30Mbps で再エンコして試してみましたが、パケットロスは確認できず!
(ただ、30Mbps だと今度は携帯側での受信が辛く、頻繁に止まっちゃいます)

SS.png

まとめ

色々と躓きましたが、最終的には目的を達成することができました。
個人的に 4Kハードウェアエンコーダーを用意せずに事前検証が行えるのはとても助かります!

17
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?