Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What is going on with this article?
@tomopyonsama

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

More than 1 year has passed since last update.

こんにちは、先日人生初屋形船に乗って興奮を隠しきれない 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ハードウェアエンコーダーを用意せずに事前検証が行えるのはとても助かります!

8
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
tomopyonsama
セロー買うたった 林道林道
cloudpack
Amazon Web Services (AWS) の導入設計、環境構築、運用・保守をサポートするマネジドホスティングサービス

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
8
Help us understand the problem. What is going on with this article?