はじめに
Jetson Nano で NVMPI を有効にした FFmpeg が動作するようになった ので、NDI プラグインも試してみました。
結論から先に言うと、問題なく NDI 送信できましたが、ラズパイカメラから NDI 送信した実績 があったので、同じ手順で進めていたところ途中でビルドに失敗した箇所があったので、備忘録を兼ねてメモに残しておきます。
Raspberry Pi と Jetson Nano のスペック比較
Raspberry Pi と Jetson Nano のスペックで GPU 性能以外 (CPU、メモリ容量、Debian 系 OS) は大きな差がないと思って手順を進めたのが間違いでした。
Jetson Nano | Raspberry Pi 3 Model B+ | Raspberry Pi 4 Model B | |
---|---|---|---|
CPU | ARM Cortex-A57(4コア 1.43GHz) | ARM Cortex-A53(4コア 1.4GHz) | ARM Cortex-A72(4コア 1.5GHz) |
メモリー | 4GB | 1GB | 1GB / 2GB / 4GB |
GPU | NVIDIA Maxwell 128コア(CUDA対応) | Broadcom VideoCore IV | Broadcom VideoCore VI |
USBコネクター | USB 3.0×4 | USB 2.0×4 | USB 3.0×2、USB 2.0×2 |
ネットワーク | 10/100/1000Mbps | 10/100/1000Mbps | 10/100/1000Mbps |
WiFi / Bluetooth | なし | IEEE802.11b/g/n/ac、 Bluetooth 4.2 | IEEE802.11b/g/n/ac、 Bluetooth 4.2 |
OS | Ubuntu (64bit) | Raspbian (32bit) | Raspbian (32bit) |
動作 OS の違い
Jetson Nano は Raspberry Pi とほぼ同じ ARM CPU を使用しているので、最初は Raspberry Pi で動作実績のあった NDI SDK LINUX ライブラリを使用しました。
しかし、FFmpeg のビルド途中でエラーになり、エラー原因を調べたところ Jetson Nano は 64bit OS (aarch64) で、NDI SDK LINUX ライブラリは 32bit バイナリでした。
NDI SDK はソースコードが公開されていないため、 64bit バイナリが提供されていなければ Jetson Nano で使用することができません。
環境
- Jetson Nano (新リビジョン B01 では試していません)
- OS イメージ JetPack 4.3 (nv-jetson-nano-sd-card-image-r32.3.1.zip)
- Ubuntu 18.04.4 LTS (Bionic Beaver)
- ウェブカメラ (Logitech, Inc. Webcam C270)
# Jetson Nano
$ uname -a
Linux jetson-desktop 4.9.140-tegra #1 SMP PREEMPT Mon Dec 9 22:47:42 PST 2019 aarch64 aarch64 aarch64 GNU/Linux
# Raspberry Pi 4 Model B+
$ uname -a
Linux raspberrypi 4.19.97-v7l+ #1294 SMP Thu Jan 30 13:21:14 GMT 2020 armv7l GNU/Linux
# NDI SDK LINUX (arm-rpi3-linux-gnueabihf)
$ file libndi.so.4.5.1
libndi.so.4.5.1: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, stripped
NDI SDK と NDI EDK
NewTek 社のホームページで NDI SDK を調べていたところ EDK (Embedded Developer Kit) を見つけました。
説明に ARM based SDK と記載されていたので、ダウンロードして確認したところ、64bit バイナリ (aarch64-newtek-linux-gnu) が含まれていました。
$ ls -l
total 52
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 aarch64-himix100-linux
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 aarch64-newtek-linux-gnu
drwxr-xr-x 6 jetson jetson 4096 4月 1 14:31 android
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 arm-himix100-linux
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 arm-himix200-linux
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 arm-hisiv300-linux
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 arm-hisiv400-linux
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 arm-hisiv500-linux
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 arm-hisiv510-linux
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 arm-hisiv600-linux
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 arm-newtek-linux-gnueabihf
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 i686-linux-gnu
drwxr-xr-x 2 jetson jetson 4096 4月 28 12:04 x86_64-linux-gnu
$ cd aarch64-newtek-linux-gnu
$ file libndi.so.4.5.1
aarch64-newtek-linux-gnu/libndi.so.4.5.1: ELF 64-bit LSB shared object, ARM aarch64, version 1 (GNU/Linux), dynamically linked, stripped
FFmpeg に NDI ライブラリを組み込む
ライブラリが入手できれば FFmpeg に NDI ライブラリを組み込んでビルドして完了ですが、もう 1 点注意があります。
FFmpeg 4.1系以降から NDI のサポートが削除された経緯
FFmpeg 3.4 で NDI がサポートされた際に ラズパイカメラから NDI 送信 を試してみましたが、その後、NewTek 社が GPL ライセンス違反で適切な対応が取られなかったことで、FFmpeg 4.1系以降から NDI のサポートが削除されました。
(参考)
https://trac.ffmpeg.org/ticket/7589
https://patchwork.ffmpeg.org/project/ffmpeg/patch/CAB0OVGpkpyFzmkuC+kO3-Er3iNYH9hpO4zDTQZbRpEyFu=fjuQ@mail.gmail.com/
ビルド手順 (FFmpeg 4.0系)
FFmpeg 4.1系以降で NDI がサポートされなくなったため、FFmpeg 4.0系 (4.0 系の最終 4.0.5) のビルド手順です。
# NDI EDK のインストール
$ mkdir NDIE
$ cd NDIE
$ wget http://new.tk/NDISDKE
$ mv NDISDKE InstallNDISDK_v4_Linux_Embedded.tar.gz
$ tar xvzf InstallNDISDK_v4_Linux_Embedded.tar.gz
$ sh InstallNDISDK_v4_Linux_Embedded.sh
$ sudo mkdir /usr/include/ndi
$ sudo cp NDI\ SDK\ for\ Linux/include/* /usr/include/ndi/
$ sudo cp NDI\ SDK\ for\ Linux/lib/aarch64-newtek-linux-gnu/* /usr/lib/
# FFmpeg のビルド
$ git clone git://source.ffmpeg.org/ffmpeg.git -b release/4.0 --depth=1
$ cd ffmpeg
$ ./configure --enable-nonfree --enable-libndi_newtek --extra-cflags="-I/usr/include/ndi/" --extra-ldflags="-L/usr/include/ndi/" --enable-libx264 --enable-gpl
$ make -j3
実行手順
ウェブカメラは /dev/video0、ウェブカメラのマイクは card 2 で認識されている場合、以下のコマンドで実行します。
画像サイズ (-s 1280x720) と フレームレート (-r 30) はウェブカメラの性能に応じて変更します。
$ ./ffmpeg -f alsa -ac 1 -thread_queue_size 4096 -i hw:2 -i /dev/video0 -s 1280x720 -r 30 -vcodec wrapped_avframe -g 50 -strict experimental -f libndi_newtek -pix_fmt uyvy422 JetsonNanoCamera
(負荷状況)
jetson_stats の jtop コマンドで確認したところ、NDI はソフトウェアエンコーディングなので 50% 程度の負荷でした。
受信側は OBS-Studio に NDI プラグインを追加して動作を確認しました。
(参考) カメラとマイクの確認方法
ウェブカメラは /dev/video0 で認識されていました。
$ lsusb
Bus 002 Device 002: ID 0bda:0411 Realtek Semiconductor Corp.
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 006: ID 15ca:00c3 Textech International Ltd. Mini Optical Mouse
Bus 001 Device 005: ID 04fe:0006 PFU, Ltd
Bus 001 Device 004: ID 04fe:0008 PFU, Ltd
Bus 001 Device 003: ID 046d:0825 Logitech, Inc. Webcam C270
Bus 001 Device 002: ID 0bda:5411 Realtek Semiconductor Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ ls /dev/video*
/dev/video0
ウェブカメラのマイクは card 2 で認識されていました。
$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 0: ADMAIF1 CIF ADMAIF1-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 1: ADMAIF2 CIF ADMAIF2-1 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 2: ADMAIF3 CIF ADMAIF3-2 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 3: ADMAIF4 CIF ADMAIF4-3 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 4: ADMAIF5 CIF ADMAIF5-4 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 5: ADMAIF6 CIF ADMAIF6-5 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 6: ADMAIF7 CIF ADMAIF7-6 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 7: ADMAIF8 CIF ADMAIF8-7 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 8: ADMAIF9 CIF ADMAIF9-8 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: tegrasndt210ref [tegra-snd-t210ref-mobile-rt565x], device 9: ADMAIF10 CIF ADMAIF10-9 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: U0x46d0x825 [USB Device 0x46d:0x825], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
v4l2-ctl コマンドでウェブカメラの性能を確認できます。
$ v4l2-ctl --list-formats-ext --device=/dev/video0
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : YUYV 4:2:2
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 160x120
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 176x144
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 320x176
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 352x288
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 432x240
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 544x288
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 640x360
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 752x416
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 800x448
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 800x600
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 864x480
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 960x544
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 960x720
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1024x576
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1184x656
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.133s (7.500 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1280x960
Interval: Discrete 0.133s (7.500 fps)
Interval: Discrete 0.200s (5.000 fps)
Index : 1
Type : Video Capture
Pixel Format: 'MJPG' (compressed)
Name : Motion-JPEG
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 160x120
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 176x144
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 320x176
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 352x288
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 432x240
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 544x288
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 640x360
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 752x416
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 800x448
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 800x600
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 864x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 960x544
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 960x720
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1024x576
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1184x656
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1280x960
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)