Raspberry Pi2 + FFmpegでMPEG2TSをハードウェアエンコード
TL;DR
- Raspberry Pi2にハードウェアアクセラレーションを有効化したFFmpegを導入した
- ハードウェアエンコードのみで20fpsを、ハードウェアデコード及びエンコードの有効化で26fpsの処理速度が得られた
- ハードウェアでコード及びエンコードを用いれば、30fpsの動画をほぼ等速で処理可能になる
はじめに
Raspberry Piにはカメラ接続端子が搭載されていることはよく知られている。 そして、カメラの入力を取り扱うためにハードウェアエンコーダが搭載されている事もまた知られている。 ところでこのハードウェアエンコーダはMPEG2をネイティブで取り扱うことができるので、これを転用してMPEG2TSをハードウェアエンコードしたいという考えが生まれる。
少し前までであればこのようなハードウェアエンコードにはgstreamerを使うのが定番だったが、 gstreamerは動画エンコードを目的としたツールではないため、大量のオプションが必要だったりとやや不便なツールだった。 ここ最近になって、FFmpegがRaspberry Piのハードウェアエンコードに対応したので、ビルドしてこれを利用する。 また、ハードウェアエンコードによる処理速度の向上を他の環境と比較する。
準備編
はじめにMPEG2用のライセンスを手に入れておく。
これについては、すでに複数の参考文献があるためここでは割愛する
基本的には購入ページに書いてある指示と、ライセンスキーが記載されたメールに書いてある指示に従えば有効化できる。
有効になっていると、次のコマンドを実行した時に結果がenabled
となる。
vcgencmd codec_enabled MPG2
次にビルド環境を整える。 Raspberry Piをセットアップした直後であれば、様々なツールが揃っていないと思われるが、とりあえず下記のコマンドを実行すると良い。
apt install build-essential raspberrypi-kernel-headers libomxil-bellagio-dev git
build-essentialは基本的なビルドツール(make
やgcc
)がインストールできる。
raspberrypi-kernel-headersはMMALを利用するためのヘッダーファイルmmal.h
をインストールする。
*1
libomxil-bellagio-devはハードウェアエンコードに必要なOpenMAX ILのライブラリを提供している。
また、今回はFFmpegのgitリポジトリからソースコードを取ってくるためgitをインストールする。
FFmpegのソースコードは次のコマンドで取得する。 今回はgithubに上がっているミラー(https://github.com/FFmpeg/FFmpeg)を利用することにした。
git clone https://github.com/FFmpeg/FFmpeg --depth 1
取得に成功したらディレクトリを移動してビルドを進めていく
cd ~/FFmpeg ./configure --arch=armel --target-os=linux --enable-mmal --enable-gpl --enable-omx --enable-omx-rpi --enable-nonfree --prefix=$HOME/usr/local
最小限でビルドするとこの形になる。--prefix
は標準のインストール先にインストールしても良いなら指定しなくて構わない。
--enable-omx-rpi
と--enable-mmal
を指定することで、Raspberry Piでのハードウェアアクセラレーションを有効にする。
この設定ではlibx264
やlibmp3lame
などは利用できないので、必要ならば別途用意してビルド時に指定をする。
make -j4 #ここは実コア数に応じて変更する。
を実行し、生成されたバイナリでハードウェアエンコーディングが有効になっているか確かめる。 有効になっていれば、次のコマンドを実行した時にそれぞれハードウェアアクセラレーションを利用するデコーダ・エンコーダが表示される。
# デコーダの表示 ./ffmpeg -decoders 2> /dev/null | grep mmal V..... h264_mmal h264 (mmal) (codec h264) V..... mpeg2_mmal mpeg2 (mmal) (codec mpeg2video) V..... mpeg4_mmal mpeg4 (mmal) (codec mpeg4) V..... vc1_mmal vc1 (mmal) (codec vc1)
# エンコーダの表示 ./ffmpeg -encoders 2> /dev/null | grep omx V..... h264_omx OpenMAX IL H.264 video encoder (codec h264)
これらが表示されていれば、ハードウェアアクセラレーションが有効になっているので、あとはインストールすれば簡単に利用できる。
make install
テスト
実際にビルドしたFFmpegを使って、適当なMPEG2TSファイルをH.264/AACのmp4ファイルにエンコードする。 また、ハードウェアアクセラレーションの効果を確認するために、幾つかの設定を変更してエンコードを試みる。
入力ファイルとして、今回はERBラボが提供しているサンプルストリームisdbt18.ts
を利用する。
isdbt18.ts
は1分間の実写動画であり、ストリームの形式はMPEG2/AACとなっている。
ffprobe
を用いて表示したストリーム情報を以下に示す。
Input #0, mpegts, from 'isdbt188.ts': Duration: 00:01:00.87, start: 109.851700, bitrate: 17304 kb/s Program 23664 Metadata: service_name : ?ERB?|ニ・1 service_provider: Stream #0:0[0x200]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv, top first), 1440x1080 [SAR 4:3 DAR 16:9], 16712 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc Stream #0:1[0x201]: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 186 kb/s
まずはハードウェアエンコーディングだけを利用してエンコードする。オプションは次の形になる。
ffmpeg -fflags +discardcorrupt -i isdbt18.ts -c:a copy -bsf:a aac_adtstoasc -c:v h264_omx -b:v 5000k -y out.mp4
-bsf:a aac_adtstoasc
と-fflags +discardcorrupt
の指定はオーディオストリームをコピーするときに発生するエラーを抑止するために指定する。
これがないとmp4への変換時にaac bitstream error
が発生する。
そして、出力のビデオコーデックとしてh264_omx
を指定する。これによってエンコード時にハードウェアを利用する。
また、ビットレートを指定しておかないと非常に低いビットレートで変換されることになり、出力結果が目も当てられなくなるのでそれなりの値を指定しておくと良い。
この時、ストリームの入出力間での対応は次のようになる。
Stream mapping: Stream #0:0 -> #0:0 (mpeg2video (native) -> h264 (h264_omx)) Stream #0:1 -> #0:1 (copy)
これを見ればわかるようにデコード時にハードウェアが利用されておらず、エンコード時にのみハードウェアが利用されている。 この時のCPU使用率は100%手前から150%程度となる。また、処理速度は20fpsとなり、ファイル実時間に対しておおよそ3/2倍の時間でエンコードが完了する。
次にデコード・エンコードともにハードウェアアクセラレーションを有効化する。
ffmpeg -fflags +discardcorrupt -c:v mpeg2_mmal -i isdbt.ts -c:a copy -bsf:a aac_adtstoasc -c:v h264_omx -b:v 5000k -y out.mp4
先ほどとの違いはオプションに-c:v mpeg2_mmal
が追加されている点で、これでハードウェアデコードが行われる。
*2
この時のCPU使用率はおおよそ50%程度となり、ハードウェアエンコードのみの場合に比べるとかなりCPU負荷が軽減されていることがわかる。 処理速度は26fpsとなり、先程に比べるとやや処理速度が向上していることがわかる。 これならば、ほぼ等速といって差し支えない程度になるため、かなり実用的ではないだろうか。
おまけ
どれくらいの速度が出ているのか実際他の環境でも比較してみる
その1
の場合
実行コマンドは
ffmpeg -fflags +discardcorrupt -i isdbt18.ts -c:a copy -bsf:a aac_adtstoasc -c:v h264 -b:v 5000k -y out.mp4
この時の処理速度は92fpsということは、ファイル実時間に対して約1/3倍の時間でエンコードできる。 さすが現行のAMDハイエンドCPUの面目躍如といったところ。
その2
実行コマンドはその1と同様。 この時の処理速度は13fpsで、ファイル実時間に対しておおよそ2倍の時間でエンコードすることになる。 ハードウェアアクセラレーションを有効化したRaspberry Pi2であれば、Sandy Bridge世代のCeleronよりも高速に動画処理ができるという結果になった。
まとめ
Raspberry PiのハードウェアエンコーダとMMALを用いた支援によって、30fps程度のエンコード能力を得られることがわかった。 これによって、地上デジタル放送などの録画ファイルを適当にRaspberry Piでエンコードするという目論見が、時間に対してもそこまで辛くなさそうということがわかってきた。 今回はGPUメモリを128MB割り当てた設定で行っているので、割当を増やした場合の処理についてもテストする必要があると感じる。
また、言うまでもないことだが
- 画面解像度の変更
- デインターレース
等を試すと、CPU処理が挟まる形になるため、処理速度が大幅に低下する。 あくまでも、MPEG2TSをH.264形式に変換するだけに使えると思っておいたほうが良いだろう。