/home/tnishinaga/TechMEMO

日々行ったこと、面白かったことを書き留めます。

Raspberry Piでh264動画をハードウェアエンコードする

Raspberry Piにはハードウェアデコード機能だけではなく、エンコード機能もあると言われていますが、日本で実際にやっている人を、あまり見たことがありません。

調べてみたところフォーラムではすでに使い方が確立してるみたいなので、私もハードウェアエンコード機能を使って、mpeg2の動画をh.264な動画に変換してみました。

gstreamer1.0のインストール

動画のデコード、エンコードにはgstreamerを使用します。

ただしハードウェアアクセラレーションをつかうライブラリはバージョン1.0以上でないと使えないみたいです。 現在提供されているgstreamerのバージョンは0.10なので、公式レポジトリからはインストールが出来ません。

他の方がコンパイルしたものをもらってきて解決します。 *1

参考サイト: http://theiopage.blogspot.jp/2013/04/enabling-hardware-h264-encoding-with.html

$ sudo sh -c "echo 'deb http://vontaene.de/raspbian-updates/ . main' >> /etc/apt/sources.list"

$ sudo aptitude update

$ sudo aptitude -y install libgstreamer1.0-0 libgstreamer1.0-0-dbg libgstreamer1.0-dev liborc-0.4-0 \
liborc-0.4-0-dbg liborc-0.4-dev liborc-0.4-doc gir1.2-gst-plugins-base-1.0 gir1.2-gstreamer-1.0 \
gstreamer1.0-alsa gstreamer1.0-doc gstreamer1.0-omx gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-bad-dbg gstreamer1.0-plugins-bad-doc gstreamer1.0-plugins-base \
gstreamer1.0-plugins-base-apps gstreamer1.0-plugins-base-dbg gstreamer1.0-plugins-base-doc \
gstreamer1.0-plugins-good gstreamer1.0-plugins-good-dbg gstreamer1.0-plugins-good-doc \
gstreamer1.0-plugins-ugly gstreamer1.0-plugins-ugly-dbg gstreamer1.0-plugins-ugly-doc \
gstreamer1.0-pulseaudio gstreamer1.0-tools gstreamer1.0-x libgstreamer-plugins-bad1.0-0 \
libgstreamer-plugins-bad1.0-dev libgstreamer-plugins-base1.0-0 libgstreamer-plugins-base1.0-dev

動画をh.264エンコードする

以下のコマンドを実行すると、mpeg2のファイル(hoge.mpg)が映像はh.264、音声はAACに変換され、hoge.mp4として保存されます。

なお、mpeg2のデコードもハードウェアで行っています。

mpeg2のデコードを行うには別途ライセンスが必要なので、以下のURLより購入して、設定してください。

http://www.raspberrypi.com/mpeg-2-license-key/

$ gst-launch-1.0 \
filesrc location=daitosho_PV.mpg  ! progressreport ! mpegpsdemux name=demuxer demuxer. ! queue ! \
mpegaudioparse ! mad ! audioresample ! audioconvert dithering=0 ! voaacenc bitrate=196000 ! mux. \
mp4mux  name=mux ! filesink location=hoge.mp4 demuxer. ! queue ! \
mpegvideoparse ! omxmpeg2videodec ! videoconvert ! \
omxh264enc target-bitrate=6000000 control-rate=variable ! video/x-h264,stream-format=byte-stream,profile=high ! \
h264parse ! mux.

実行結果

今回はサイズが1280x720で1分50秒ほどの動画を、サイズそのままにh.264に変換してみました。

以下、変換元動画の詳細です。

$ ffprobe daitosho_PV.mpg 
avprobe version 0.8.10-6:0.8.10-1+rpi1, Copyright (c) 2007-2013 the Libav developers
  built on Mar 22 2014 02:13:15 with gcc 4.6.3
Input #0, mpeg, from 'daitosho_PV.mpg':
  Duration: 00:01:49.92, start: 0.477322, bitrate: 12425 kb/s
    Stream #0.0[0x1e0]: Video: mpeg1video, yuv420p, 1280x720 [PAR 1:1 DAR 16:9], 12000 kb/s, 24 fps, 24 tbr, 90k tbn, 24 tbc
    Stream #0.1[0x1c0]: Audio: mp2, 48000 Hz, stereo, s16, 192 kb/s

こいつを食わせて、先ほどのコマンドを実行します。

$ ~コマンド省略~
パイプラインを一時停止 (PAUSED) にしています...
Pipeline is PREROLLING ...
Pipeline is PREROLLED ...
パイプラインを再生中 (PLAYING) にしています...
New clock: GstSystemClock
progressreport0 (00:00:05): 5898240 / 170721280 bytes ( 3.5 %)
progressreport0 (00:00:10): 12681216 / 170721280 bytes ( 7.4 %)
progressreport0 (00:00:15): 18972672 / 170721280 bytes (11.1 %)
progressreport0 (00:00:20): 25165824 / 170721280 bytes (14.7 %)
progressreport0 (00:00:25): 31358976 / 170721280 bytes (18.4 %)
progressreport0 (00:00:30): 37355520 / 170721280 bytes (21.9 %)
progressreport0 (00:00:35): 42958848 / 170721280 bytes (25.2 %)
progressreport0 (00:00:40): 49086464 / 170721280 bytes (28.8 %)
progressreport0 (00:00:45): 55312384 / 170721280 bytes (32.4 %)
progressreport0 (00:00:50): 61472768 / 170721280 bytes (36.0 %)
progressreport0 (00:00:55): 67764224 / 170721280 bytes (39.7 %)
progressreport0 (00:01:00): 74055680 / 170721280 bytes (43.4 %)
progressreport0 (00:01:05): 79495168 / 170721280 bytes (46.6 %)
progressreport0 (00:01:10): 85852160 / 170721280 bytes (50.3 %)
progressreport0 (00:01:15): 92110848 / 170721280 bytes (54.0 %)
progressreport0 (00:01:20): 98533376 / 170721280 bytes (57.7 %)
progressreport0 (00:01:25): 104759296 / 170721280 bytes (61.4 %)
progressreport0 (00:01:30): 110886912 / 170721280 bytes (65.0 %)
progressreport0 (00:01:35): 116654080 / 170721280 bytes (68.3 %)
progressreport0 (00:01:40): 122880000 / 170721280 bytes (72.0 %)
progressreport0 (00:01:45): 129138688 / 170721280 bytes (75.6 %)
progressreport0 (00:01:50): 135397376 / 170721280 bytes (79.3 %)
progressreport0 (00:01:55): 141656064 / 170721280 bytes (83.0 %)
progressreport0 (00:02:00): 148045824 / 170721280 bytes (86.7 %)
progressreport0 (00:02:05): 153649152 / 170721280 bytes (90.0 %)
progressreport0 (00:02:10): 159907840 / 170721280 bytes (93.7 %)
progressreport0 (00:02:15): 166166528 / 170721280 bytes (97.3 %)
Got EOS from element "pipeline0".
Execution ended after 138227846629 ns.
パイプラインを一時停止 (PAUSED) にしています...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

なんと、変換時間は驚きの2分15秒……ハードウェアのちから恐るべし。

これならRaspberry Piを動画変換サーバーとして、十分使える速度だと思います。

gstreamerの話

余談ですが、このgstreamerを動かすコマンドの理解と構築がなかなかに鬼門でした。

海外サイトやフォーラムは、いかにカメラからの入力をデコードして、エンコードして保存するかばかりを考えていて*2、私のように単純な動画変換に使ってる人はいないみたいです……(そのためピッタリ参考になる資料が無く……トライアンドエラーで一日中……)

基本的な考え方は、入力ソースを

  • demuxer
  • parser
  • encoder
  • muxer

の順に通して動画の変換をしたりするみたいです。

基本は片方の変換しかできず、映像と音声両方を変換したいときは、道中にセーブポイントを作って、その状態をキューにプッシュして、音声の変換後に取り出して、今度は動画を変換して、2つをmuxerで1つにまとめる……という非常に面倒な作業が必要になるみたいです。 よくわからん。

ネットワーク経由でやりとりしたりもできるので、多分上手いことやれば、

  • パワーの有るマシンでデコード→Raspberry Piでエンコード

ということもできるはずです。

その方式ならmpeg2ライセンスも要りませんし。 エンコード機能を使うためにはライセンス必要でした。

とりあえず私は一日中調べまわって疲れたので、寝ます。

おやすみなさい。

参考ページ

http://theiopage.blogspot.jp/2013/04/enabling-hardware-h264-encoding-with.html http://gstreamer.freedesktop.org/src/gst-omx/ http://www.raspberrypi.org/forums/viewtopic.php?f=70&t=59412

追記

某だめげーのOPを変換したところ、再生できない謎のファイルが出来た。 原因は不明。

gstreamerに渡すパラメータは、使ってるコーディックを決め打ちで設定する必要があるみたいなので、柔軟性が全くない。

映像はgstreamer、音声はffmpeg等で処理して、最後にMP4Boxでまとめる…という手法の方がいいのかもしれない。

音声と映像を分けてエンコして、後でまとめたらすごい音ズレするようになった。なぜ。

後は変換するとフレームレートが30fpsから25fpsに変更されてた。なんで。

*1:公式からソースコードでは提供されているみたいなので、これをコンパイルしてもいいかもしれません

*2:俺は二次元美少女の動画を変換したいんだ!!