Raspberry Pi 3 のハードウェアエンコーダーを使う ffmpeg のビルドのしかた

Raspberry Pi 3 のハードウェアエンコーダーを使える ffmpeg のビルド方法の備忘録です。

自分用の備忘録なので前置きとか一切なし。

まず Raspbian の Strech をインストールしておく。 Strech は2017/09にリリースされた。 一つ前の Jessie には ffmpeg が入ってない。 このあたりは libav と絡んだゴタゴタがあって それはそれで面白いのだけれどこの記事の本題ではないので脱線はここまで。

次にソースパッケージを有効にする。 ffmpeg をビルドするのに build-depsource を取得できるようにするため。 コマンドでやるとこんな感じになる。 一応 .bak にバックアップを作ってるのでなんかあったらそれで戻そう。

$ cd /etc/apt
$ find . -name '*.list' | xargs sudo sed -i.bak -e 's/^#dev-src/dev-src/'
$ sudo apt update

次に ffmpeg を入れる。 依存ライブラリをインストールした状態にするのと、 configure オプションを再利用するため。 自分で必要なものを入れる自信があれば、実は無くても良いはず。

$ sudo apt install ffmpeg

で ffmpeg のビルドに必要なモノ、ライブラリとかツール類をインストールする。

$ sudo apt build-dep ffmpeg

んで次はソースを持ってくる。 以下ではホームに ffmpeg/ というディレクトリを作って、 そこに展開して cd している。 記事執筆時点の ffmpeg は 3.2.5 なので、 ソースコードは ~/ffmpeg/ffmpeg-3.2.5 に入る。

$ mkdir ~/ffmpeg && cd !$
$ apt source ffmpeg
$ cd ffmpeg-3.2.5

あとは configure とコンパイル。 configure のオプションは ffmpeg の実行時に表示されるものから -prefix=/usr を削除して、 --enalbe-omx-rpi--enable-mmal を追加する。 あとの変更 (--extra-version とか) お好みで。

$ ./configure --extra-version=2 --toolchain=hardened \
  --libdir=/usr/lib/arm-linux-gnueabihf \
  --incdir=/usr/include/arm-linux-gnueabihf --enable-gpl --disable-stripping \
  --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa \
  --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca \
  --enable-libcdio --enable-libebur128 --enable-libflite \
  --enable-libfontconfig --enable-libfreetype --enable-libfribidi \
  --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libopenjpeg \
  --enable-libopenmpt --enable-libopus --enable-libpulse \
  --enable-librubberband --enable-libshine --enable-libsnappy \
  --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora \
  --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack \
  --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzmq \
  --enable-libzvbi --enable-omx --enable-openal --enable-opengl \
  --enable-sdl2 --enable-libdc1394 --enable-libiec61883 --enable-chromaprint \
  --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared \
  --enable-omx-rpi --enable-mmal 
$ make -j4

コンパイルは30分くらいかかった。 その際に CPU の発熱がすごくて温度警告がでる(初めて見た!)。 温度警告は 80~85℃ で出て 85℃ を超えるとクロックが落ちるらしい。 速く安全に終わらせたいならヒートシンクを付けるなどの熱対策が要る。 自分は放熱できるケースを買っておいたのでそれに入れ替えた。

コンパイルが無事に終わったらあとはインストール。

$ sudo make install

USBカメラを接続して ffmpeg に処理させるときのオプションがこんな感じ。 HLS 用になんか良い感じになるように調整してみた。

ffmpeg -f alsa -i hw:1 -s 320x240 -i /dev/video0 \
  -vcodec h264_omx -acodec aac -f segment \
  -segment_format mpegts \
  -segment_time 4 \
  -segment_list_size 8 \
  -segment_list_type m3u8 \
  -segment_list stream.m3u8 \
  -segment_list_flags +live \
  stream%05d.ts

雑にオプションを解説しておく。 -f alsa -i hw:1 でオーディオも処理できるようになる。 -s 320x240 -i /dev/video0 で Video4Linux2 のカメラから取り込める。 フォーマットとかエンコードは基本自動判定してくれるみたい。 -vcodec h264_omx が本記事の肝で、 動画部分をハードウェアエンコーダーを使って H264 にエンコードしている。 -acodec aac は音声部分のAACエンコーダー。libfaacは入ってない。 以降は HLS 用に分割ファイルとして出力するためのモノだが、 -segment_time 4-segment_list_size 8 の2つは 私の環境で遅延を10秒にまで縮めるのに大きく寄与した。

なお HLS のテストには mattn/webcam-live を魔改造して使った。

-vcodec h264 とするとソフトウェアエンコーダーが使えるのだが、 その際は CPU 使用率 350%、ラズパイ3はクアッドコアなので最大400%だから ほぼフルに使って実時間の 50% の速度しかでなかった。 つまり1秒変換するのに2秒かかる。 それに対してハードウェアエンコーダーなら CPU 利用率はわずか 50% 程度に抑えられ、 なおかつリアルタイムでのエンコードができた。 また 640x480 程度までならリアルタイムのエンコードができたが、 1280x720 では 80~95% 程度でやや遅れる感じ。

なんにせよハードウェアエンコーダーは素晴らしい。

参考にした資料