📹

ラズパイ Zero 2 Wで映像をSRT伝送 60fps/最適化編

に公開

目的

本記事では、Raspberry Pi Zero 2 W によるSRT受信で60FPS化,画質,色味の改善をします。
https://zenn.dev/qua_robotics/articles/35e997c190289d
の続きです。

環境

受信側:
・Raspberry Pi Zero 2 W
 -OS: Raspberry Pi OS Desktop 64bit (Bookworm)
  ※以降、Bullseyeより最新のOSバージョンの手順です。
 -GStreamer version 1.22.0
https://www.switch-science.com/products/7600

・microSDカード
https://www.amazon.co.jp/dp/B08PTNWQ6P?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1

・HyperPixel 4.0 - Hi-Res Display for Raspberry Pi(Non-Touch)
https://www.switch-science.com/products/5984

・ラズパイの電源関連
 -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