ラズパイ Zero 2 Wで映像をSRT伝送 60fps/最適化編
目的
本記事では、Raspberry Pi Zero 2 W によるSRT受信で60FPS化,画質,色味の改善をします。
の続きです。環境
受信側:
・Raspberry Pi Zero 2 W
-OS: Raspberry Pi OS Desktop 64bit (Bookworm)
※以降、Bullseyeより最新のOSバージョンの手順です。
-GStreamer version 1.22.0
・microSDカード
・HyperPixel 4.0 - Hi-Res Display for Raspberry Pi(Non-Touch)
・ラズパイの電源関連
-Micro USBケーブル
-5V/2.5Aくらい供給できるアダプター
配信側:
・Windows 11
・OBS 31.0.3
最適化(FPS,画質,色味)
結論
結論として、デスクトップを停止すれば60FPS出ました。
デスクトップ有りでは、頑張っても41FPSくらいが限界でした。その場合、OBSの配信FPSを41にそろえると等倍速になります。
FPSの表示(確認用)
OBSからの配信FPSを60にしてみます。
以下で、受信画面を表示しながら、その下部にFPSを表示します。
gst-launch-1.0 -v srtserversrc uri="srt://:15000" latency=100 ! decodebin ! videoconvert ! fpsdisplaysink video-sink=autovideosink sync=false -v
VNCから実行すると、30FPSで配信しても、60FPSで配信してもラズパイは30FPSしか出ていないことがわかります。
なので60FPSで配信すると、フレームがドロップしていないのでスローモーションみたいになってしまっています。
デスクトップの停止
# デスクトップ一時停止
sudo systemctl stop lightdm.service
# デスクトップ停止(再起動後も影響)
sudo systemctl disable lightdm.service
ちなみに戻すときには、
# デスクトップ一時起動
sudo systemctl start lightdm.service
# デスクトップ起動(再起動後も影響)
sudo systemctl enable lightdm.service
sudo systemctl disable lightdm.serviceのあと、再起動すると、仮想コンソールtty1が画面に表示されてしまいます。
ローカルから操作する予定はないので、
sudo systemctl disable getty@tty1.service
で停止します。
この状態でSRT受信すると、タイトルバーも無く、フルスクリーンで表示されます。
SSHから
デスクトップが起動していないのでVNCからはできません。
SSHから操作する際、そのままではxvimagesinkは使えません。
なのでglimagesinkまたはautovideosinkで表示使用します。
gst-launch-1.0 -v srtserversrc uri="srt://:15000" latency=100 ! decodebin ! videoconvert ! fpsdisplaysink video-sink=autovideosink sync=false -v
デスクトップ起動中のSSH(VNC負荷のみ回避)
xvimagesinkで表示したい場合は、DISPLAY=:0でディスプレイ指定。
glimagesinkの場合は、DISPLAY=:0なくても動きます。
DISPLAY=:0 gst-launch-1.0 -v srtserversrc uri="srt://:15000" latency=100 ! decodebin ! videoconvert ! fpsdisplaysink video-sink=autovideosink sync=false -v
効果の確認をしてみましょう。
# CPU使用量の表示
top
「gst-launch-1.0」が受信描写です。
===VNCから操作したとき===
====SSHから操作したとき===
===デスクトップ停止後、SSHから操作したとき===
CPU使用率が劇的に下がりました。
GPUメモリを増やしてみる
現在の割当量をターミナルで確認
vcgencmd get_mem gpu
GPUに割り当てた後の残りがCPUに割り当てられる。
/boot/firmware/config.txt に
gpu_mem=128
を直接追加。
OBSの設定
< OBS→設定→出力→出力モードを詳細→配信設定→映像エンコーダを選択 >
・レート制御をCBR
・QuickSyncH.264のときは、Bフレームを0、
(ラズパイデスクトップ停止のとき、プロファイルをhigh、遅延をultra-low、ビットレート5000kbps)
・x264のときはプリセットをultrafast
< OBS→設定→映像→FPS >
・60FPS
(デスクトップ有りでは、実際の受信FPS限界に合わせる。今回の場合、41FPSくらい)
ハードウェアデコーダの使用
pi zeroでの負荷を下げるために、明示的にハードウェアデコーダを使用するように指定してみます。
(decodebinで自動的にv4l2h264decが使われていましたが…)
以下でハードウェアコーデックが使用可能か確かめます。
gst-inspect-1.0 | grep h264
→ハードウェアデコーダv4l2h264dec
ハードウェアエンコーダv4l2h264encです。
ちなみに、x264encはソフトウェアエンコーダ
avdec_h264はソフトウェアデコーダです。
DISPLAY=:0 gst-launch-1.0 srtserversrc uri=srt://:15000?mode=listener ! tsdemux ! h264parse ! v4l2h264dec ! videoconvert ! fpsdisplaysink video-sink=xvimagesink sync=false -v (tsdemux入れないと乱れる、OBSがts配信前提?)
スワップファイルの拡張
現状のスワップファイルのサイズ
# メモリ量をMB単位表示
free -m
スワップの一時停止
sudo swapoff --all
sudo systemctl stop dphys-swapfile
1GBに拡張( /etc/dphys-swapfile 内の下記の値を編集)
デフォルトでは512MBでした。これでも十分な気がします。
CONF_SWAPSIZE=1024
スワップの起動
sudo systemctl start dphys-swapfile
画質の改善
単純に配信映像側をできる限り高画質にしてください。
色味の調整
実際の受信映像をディスプレイで見てみると、画面白みががって、色が薄いと思います。(VNCで見ると普通)
ログによると、入力規格がbt709(HD向け)なのに、出力規格がbt601(SD向け)になっているので合わせます。
DISPLAY=:0 gst-launch-1.0 srtserversrc uri=srt://:15000?mode=listener latency=100 ! decodebin ! videoconvert ! video/x-raw,colorimetry=bt709 ! fpsdisplaysink video-sink=autovideosink sync=false -v
受信側で色補正(処理重い)
CPU使用率105%くらいになって、10FPSしか出ませんでした。
DISPLAY=:0 gst-launch-1.0 srtserversrc uri=srt://:15000?mode=listener latency=100 ! decodebin ! videoconvert ! videobalance saturation=1.3 contrast=1.1 brightness=-0.1 ! video/x-raw,colorimetry=bt709 ! fpsdisplaysink video-sink=autovideosink sync=false -v
メモ:
(bt709指定はvideoconvertの後ろでないと動かない,video/x-raw,format=RGB入れると動かない。
brightness=-1.0~1.0,contrast=0.0~2.0,saturation(彩度)=0.0~2.0)
OBSでの色補正
そのままだと画面白みががって、色が薄いと思います。
ディスプレイのHyper Pixel 4.0が18bitカラーなのが影響していると思われます。
普段目にする24bitカラーに寄せていきます。
OBS→ソース→画面キャプチャを右クリック→フィルタ→+
(OBS:コントラスト0.35,輝度-0.024,彩度0.6でちょうどよさそうです。)
参考
GStreamerで映像処理のボトルネックを見つける方法
[Raspberry Pi4] GPUに割り当てるメモリを増やす
swap(仮想メモリ)のチューニング
Discussion