Radxa Zero 3WでH.264ハードウェアエンコード & 映像伝送

# はじめに
この記事では、Radxa Zero 3W を用いて Rockchip MPP による H.264 ハードウェアエンコードを行い、LAN 内の別PCへ映像を低遅延で配信する手順を解説します。  
Radxa Zero 3W は Raspberry Pi Zero 2W 相当以上の性能を持ち、ラインナップも豊富であるため、Raspberry Pi Zero 2Wの代替として期待されています。しかし、国内の情報が少なく、公式イメージでは MPP が動作しないケースも確認できたため、本稿では Armbian を利用した構築手順と使用方法をまとめました。  

この記事は以下のような方を対象とします：  
- Radxa Zero 3w でのハードウェアエンコードに挑戦したい
- Linux上でのCLI操作に慣れており、GStreamerやエンコードに関して基本的な理解がある  
- UVCカメラの取り扱い方法を理解している  


# ハードウェア
- Radxa Zero 3W本体（筆者はメモリ2GB、emmc16GBモデルを使用）
- UVC対応のUSBカメラモジュール
- Micro SDカード（emmcへOSを書き込む前に使用）
- USBキーボード（OSセットアップに使用）
- モニターとmicro HDMIケーブル（OSセットアップに使用）

# 手順
1. Radxa Zero 3WへのOSの書き込み・設定
2. 必要なライブラリのビルド・インストール
3. 動作確認

# 使用OSについて
最初はRadxa公式のOSを使用しようとしていました。
公式では以下4つのOSイメージが提供されています。
- Debian Xfce
- Debian CLI
- Ubuntu Xfce
- Ubuntu CLI

筆者はSBCのスペックを最大限利用するため、CLIでの利用を行うことが多いです。
しかし、公式のDebian CLIイメージは現在正常動作しない状態になっているとのアナウンスがされています。また筆者の環境では、Ubuntu CLIイメージを用いると、MPP（RockChipを用いたメディア処理に必要なライブラリ）が正常動作しませんでした。調査すると、rk35xx向けのベンダー・カーネルで動作確認が取れている事例が多かったので、カーネルイメージやデバイスツリーの問題かと思われます。
よって公式イメージを使うのではなく、ArmbianのRadxa Zero 3W向けのMinimal/IOTイメージを使用することにしました。

# OSインストール
まず以下のサイトからMinimal/IOTイメージをダウンロードします。
[Radxa Zero 3W_3E - Armbian](https://www.armbian.com/radxa-zero-3/)
SDカードにOSを書き込むため、[balenaEtcher](https://etcher.balena.io/)を利用します。

ダウンロードが完了したら、balenaEtcherを起動し、SelectImageから先ほどダウンロードしたArmbianのOSイメージを選択、SelectDriveから書き込み先ドライブを選択し、Flashを押してOSをSDカードに書き込みます。

書き込みが完了したら、Radxa Zero 3WにUSBキーボード、モニターを接続し、SDカードを挿入してから電源ケーブルを接続します。
少し待つとOSが起動し、初期設定画面になるので、指示に従い、ユーザー名やパスワードなどの初期設定を完了させます。
筆者の環境では以下のようになりました。
```shell-session
$ uname -a
Linux radxa-zero3 6.1.115-vendor-rk35xx #1 SMP Tue Jun  3 13:10:51 UTC 2025 aarch64 GNU/Linux
```

# 初期設定
`sudo armbian-config`から`Network`→`Basic network setup`→`wlan0`へと進み、Wifiを設定します。筆者の環境ではこの段階でWifiの設定ができませんでした（後述）。
Wifiの設定が完了したらもう一度`armbian-config`を開き、`System`→`Storage`→Installへと進み、SDカードの中身をemmcへクローンします。環境によっては数十分かかる場合があります。
完了したら一度電源を落とし、SDカードを抜いて再度起動します。正常に起動すれば、eMMC への書き込みが成功しています。
ここまで完了すればsshを利用して本体を使うことも可能ですので、適宜扱いやすい環境で作業を行なってください。

## Wifiの設定ができない場合
OSのインストール直後にWifiの設定ができない場合（項目が出てこない場合）は、`apt update`と`apt upgrade`を行ってから、もう一度`armbian-config`を開いてWifiの設定を行ってください。
この際ネットワーク接続が必要なので、筆者は手持ちのUSBイーサネットアダプタを利用して有線LAN経由でパッケージのアップグレードを行いました。Wifi設定が完了すれば有線LANは不要です。

## emmcから起動できない場合
もう一度SDカードから起動し、emmcへのブートローダの書き込みを試し、emmcへのイメージ書き込みをやり直してください。
SDカードからの起動もできない場合は、以下の手順を試してみてください。
1. 一度電源を外し、SDカードを挿入する
2. Zero 3W本体についているmaskromボタンを押しながら電源アダプターを挿す

この方法は本来maskromモード（PCと接続しemmcなどに書き込みできる）を起動する方法ですが、SDカードを挿しながら実行することでemmcにブートローダが存在する状態でもSDカードから起動することができます。

# 必要なライブラリのビルドとインストール
以下のライブラリを使用します
- MPP
- Gstreamer
- Gstreamer-Rockchipプラグイン
- v4l-utils（必要であれば）

## 下準備
### ビルド環境の準備
```shell
sudo apt update
sudo apt upgrade
sudo apt install meson ninja-build pkg-config build-essential libdrm-dev cmake
```
### MPPが利用可能な状態かの確認
カーネルの確認
```shell
# rk35xx向けのベンダーカーネルであることを確認
$ uname -r
6.1.115-vendor-rk35xx
```
MPPのデバイスノードが生成されているかの確認。
これが存在しない場合は、MPPを利用するためのデバイスツリーがロードされていないため、エンコーダが利用できない。
```shell
# これが存在すればOK
ls -l /dev/mpp_service
```

### デバイスノードの権限設定
以下のファイルを作成して記述を追加
```shell
# /etc/udev/rules.d/11-rockchip-mpp.rules
KERNEL=="mpp_service", MODE="0660", GROUP="video"
SUBSYSTEM=="dma_heap", KERNEL=="system-uncached", MODE="0666", GROUP="video"
```
設定反映後、ユーザーを video グループに追加します。
```shell
sudo udevadm control --reload
sudo udevadm trigger
# 変更を反映させるには再ログインが必要です。
sudo usermod -aG video $USER
```
全て完了した後に、usermodを反映するため再ログインし、事前準備は完了です。

## MPPのインストール
MPPはRockChipでハードウェアエンコードを行うために必要なライブラリです。今回は映像伝送を行う際にh264でのエンコードを行います。ソフトウェアを用いてエンコードすることも可能ですが、小型SBCではCPU負荷が大きくなりすぎるので、ハードウェアエンコードを行うのが一般的です。

### ソース取得
```shell
git clone https://github.com/rockchip-linux/mpp.git
cd mpp
```
### ビルドとインストール
```shell
cd build/linux/aarch64
./make-Makefiles.bash
make -j$(nproc)
sudo make install
sudo ldconfig
```
```shell-session
$ ls /usr/local/lib
librockchip_mpp.a   librockchip_mpp.so.0  librockchip_vpu.so    librockchip_vpu.so.1  python3.11
librockchip_mpp.so  librockchip_mpp.so.1  librockchip_vpu.so.0  pkgconfig
```


## Gstreamerのインストール
[公式の手順](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html?gi-language=c)に従います。
全てが必須であるわけではないため、もしインストールできないライブラリが存在した場合は適宜省いてください。
```shell
sudo apt install \
    libgstreamer1.0-dev \ 
    libgstreamer-plugins-base1.0-dev \
    libgstreamer-plugins-bad1.0-dev \ 
    gstreamer1.0-plugins-base \
    gstreamer1.0-plugins-good \
    gstreamer1.0-plugins-bad \
    gstreamer1.0-plugins-ugly \
    gstreamer1.0-libav gstreamer1.0-tools \
    gstreamer1.0-x gstreamer1.0-alsa \ 
    gstreamer1.0-gl gstreamer1.0-gtk3 \  
    gstreamer1.0-qt5 gstreamer1.0-pulseaudio
```
```shell-session
$ gst-launch-1.0 --version
gst-launch-1.0 version 1.22.0
GStreamer 1.22.0
https://tracker.debian.org/pkg/gstreamer1.0
```

## Gstreamer Rockchipプラグイン
gstreamerからRockchip搭載のエンコーダやデコーダを扱うためのライブラリです。今回はmpph264encエレメントを利用します。公式に提供されているリポジトリが存在しないため、ミラーサイトからダウンロードします。

```shell
git clone https://github.com/JeffyCN/mirrors.git 
cd rockchip_mirrors
git checkout gstreamer-rockchip

# 非常に大きいリポジトリであるため、時間がかかりすぎる場合は以下の方法を試してください
wget https://github.com/JeffyCN/mirrors/archive/refs/heads/gstreamer-rockchip.zip
unzip gstreamer-rockchip.zip
cd mirrors-gstreamer-rockchip
```

### ビルドとインストール
```shell
mkdir build && cd build
meson .. \
  -Dprefix=/usr \
  -Dlibdir=/usr/lib/aarch64-linux-gnu
ninja
ninja install
```

```shell-session:mpph264encなどのエンコーダ・デコーダが表示されればOK
$ gst-inspect-1.0 | grep mpp
rockchipmpp:  mpph264enc: Rockchip Mpp H264 Encoder
rockchipmpp:  mpph265enc: Rockchip Mpp H265 Encoder
rockchipmpp:  mppjpegdec: Rockchip's MPP JPEG image decoder
rockchipmpp:  mppjpegenc: Rockchip Mpp JPEG Encoder
rockchipmpp:  mppvideodec: Rockchip's MPP video decoder
rockchipmpp:  mppvpxalphadecodebin: VP8/VP9 Alpha Decoder
```

## v4l-utils（必要であれば）
```shell
sudo apt install v4l-utils
```

# 動作確認
今回はGstreamerを用いてLAN上の別のコンピュータに映像を配信することで動作確認を行います。
まず、Radxa Zero 3WにUVCカメラを接続してください。
```shell-session
$ v4l2-ctl --list-devices
HD USB CAMERA: HD USB CAMERA (usb-xhci-hcd.4.auto-1.1):
	/dev/video0
	/dev/video1
	/dev/media0
```
今回使用するUVCカメラはMJPEGで映像を取得するタイプなので、MJPEGデコード→h264エンコード→lan内に配信といった流れで映像を視聴します。また、今回は簡単な動作確認のみ行うため、rtpパケットをUDPで直接送信します。

まずは視聴したいPCにもGstreamerをインストールして
```shell
gst-launch-1.0 -v \
  udpsrc port=5000 caps="application/x-rtp,media=video,encoding-name=H264,payload=96,clock-rate=90000" \
    ! rtph264depay \
    ! avdec_h264 \
    ! videoconvert \
    ! autovideosink sync=false
```
この際、ファイアウォール等でUDP 5000番ポートが制限されていないことを確認してください。

次にZero 3W側で
```shell
gst-launch-1.0 -v \
  v4l2src device=/dev/video0 \
    ! image/jpeg, width=1920, height=1080, framerate=30/1 \
    ! jpegparse \
    ! mppjpegdec \
    ! video/x-raw, format=NV12, width=1920, height=1080, framerate=30/1 \
    ! mpph264enc \
    ! h264parse config-interval=1 \
    ! rtph264pay pt=96 config-interval=1 mtu=1400 \
    ! udpsink host=192.168.x.x port=5000 sync=false
 ```
`host=192.168.x.x`は視聴PCのIPアドレスに書き換えてください。
 
これで映像が視聴できれば動作確認完了です。
もしUVCカメラが直接rawを吐き出す場合はmjpegデコーダを通さずにvideoconvertしてmpph264encに流すようパイプラインを書き換えてください。また、視聴PCにGstreamerをインストールしたくない場合はZero 3W側にrtspサーバーを立てて、VLCなどで視聴してください。

# 終わりに
今回、Radxa Zero 3W上でMPPを用いたハードウェアエンコードと映像伝送を行う方法をまとめました。Radxa Zero 3Wを試してみる際に役立てていただけたら幸いです。
また、この記事は執筆日（2025/6/17）時点での情報ですので、今後方法が変わる可能性がある旨ご了承ください。不明な点や感想などのコメントお待ちしております。
次のステップとして、h265エンコードやWANを介した映像伝送にも挑戦してみてください。これらの内容も時間があれば記事にしたいと思います。