Intel Media SDKとIntel QSVに対応したffmpegをビルドして爆速H.264エンコード(Ubuntu 16.04)
前回までの記事で、Intel Media Driverをインストールし、無事にドライバの読み込みまでは完了したところである。
これでVAAPIを用いたエンコードは出来るのだが、ffmpegのバージョンがあがり、この状態からQSVを使ったエンコードまでできるようになった。
ご承知の通り、VAAPIを使ったエンコードはエンコードオプションが非常に少なく、使い勝手が良いとは言えない。対照的に、Intel QSVを用いると、オプションは豊富となり、さらに少しだけ「ファイルが重たくなってしまう」というような事象にも対応出来るようだ。
Intel Media SDKをインストールする
まずはじめに、Intel Media SDKをインストールしておかなければ、QSVに対応することができない。ただし、インストール自体は非常に簡単である。
基本的には、公式サイトの通り。ただし最新版のLibvaが入っていれば、タグをcheckoutする必要はない。
$ wget https://github.com/intel/compute-runtime/releases/download/18.24.10921/intel-opencl_18.24.10921_amd64.deb$ sudo dpkg -i intel-opencl_18.24.10921_amd64.deb$ git clone https://github.com/Intel-Media-SDK/MediaSDK msdk$cd msdk$ mkdir build$cd build$ cmake ..$ time make -j8$ sudo make install$export PKG_CONFIG_PATH=/opt/intel/mediasdk/lib/pkgconfig:$PKG_CONFIG_PATH
なお、当方の環境ではビルド中にOpenCL環境が少し欠けている点があり(具体的には「cl.app
」と「cl_va_api_media_sharing_intel.h
」)、それぞれを別々に調達し/usr/include/CL/配下に配置してあげた。この方法が正しいのかどうかは不明であるが、とにかくmakeは通った。
最後の行は、/opt/intel/mediasdk/lib/pkgconfig
配下にMedia SDKのpkg-configファイルが格納されているので、ここにpkg-configが参照できるよう環境変数に追加をしている次第。
ffmpegをビルドする
今回は、Intel QSVやその他諸々に対応したffmpegを一からビルドしていく。バージョンもffmpeg4となり、機能は相当に強化されているらしい。
基本的には、リポジトリに登録されているx264等は少し機能が遅れていることから、これらに関してもソースからコンパイルをしていく。
実際には、公式サイトをみながら進めていくと良い。
依存関係のあるコンポーネントのインストール
依存関係がいくつかあるので、これだけ注意しておきたい。x264等個別のエンコーダーのインストールは、上記の公式サイトを参考としていただければ幸いである。
$ sudo apt-get update -qq && sudo apt-get -y install autoconf automake build-essential cmake git-core libass-dev libfreetype6-dev libsdl2-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-devnasm yasm libgtk-3-0 libgdk-pixbuf2.0
QSV対応のffmpegをコンパイル&インストールする
ようやくFFMpegのインストールとなる。忘れてはならないのは、Intel QSVを有効にしておくこと。その他、現在のffmpegのエンコードオプションはffmpegを実行すると出てくるので、それを参考にすると良い。
また、デフォルトではPKG_CONFIG_PATHが別に設定されることを想定していないため、この部分は少しだけ修正。
$cd ~/ffmpeg_sources$ git clone https://github.com/FFmpeg/FFmpeg ffmpeg$cd ffmpeg$ PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig:$PKG_CONFIG_PATH" ./configure \
--prefix="$HOME/ffmpeg_build" \
--pkg-config-flags="--static" \
--extra-cflags="-I$HOME/ffmpeg_build/include" \
--extra-ldflags="-L$HOME/ffmpeg_build/lib" \
--extra-cflags="-I/opt/intel/mediasdk/include" \
--extra-ldflags="-L/opt/intel/mediasdk/lib" \
--extra-ldflags="-L/opt/intel/mediasdk/plugins" \
--extra-libs="-lpthread -lm" \
--bindir="$HOME/bin" \
--enable-vaapi \
--enable-libdrm \
--enable-libtheora \
--enable-opencl \
--enable-gpl \
--enable-libmfx \
--enable-libaom \
--enable-libass \
--enable-libfdk-aac \
--enable-libfreetype \
--enable-libmp3lame \
--enable-libopus \
--enable-libvorbis \
--enable-libvpx \
--enable-libx264 \
--enable-libx265 \
--enable-nonfree
$ make -j8$ make install
これで、%HOME/bin
ディレクトリの中にffmpegができあがる。$HOME/binにパスを通してこのまま使うことも可能なのだが(というか、ffmpegの推奨はこれである)、少し気持ちが悪いのでコピーしたりコンパイルオプションを変えたりしておこう。
インストールされると、ffmpegのエンコーダーにh264_qsvが追加されているのが分かる。
$ ffmpeg -encoder s | grep qsv
V..... h264_qsv H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration) (codec h264)
V..... hevc_qsv HEVC (Intel Quick Sync Video acceleration) (codec hevc)
V..... mjpeg_qsv MJPEG (Intel Quick Sync Video acceleration) (codec mjpeg)
V..... mpeg2_qsv MPEG-2 video (Intel Quick Sync Video acceleration) (codec mpeg2video)
QSV対応ffmpegの使い方やオプション
さて、これでIntel Media SDKを使ってffmpegからQSVエンコードをする準備が整った。
使用するコーデックはh264_qsv
。使用出来るOptionは、やはり公式サイトが詳しい。
また、非常に充実しているのが下記のサイトで、非常に詳しい使い方が手に入る。
機能上VAAPIと大きな違いは、インタレースの解除オプションがあるところだろうか(deinterlace_qsv
)。QSVを使用する際に利用出来るオプションの詳細は、ffmpeg -h encoder=h264_qsv
を実行することで確認可能だ。
$ ffmpeg -h encoder=h264_qsv
-async_depth <int> E..V...... Maximum processing parallelism (from1 to INT_MAX) (default4)
-avbr_accuracy <int> E..V...... Accuracy of the AVBR ratecontrol (from0 to INT_MAX) (default0)
-avbr_convergence <int> E..V...... Convergence of the AVBR ratecontrol (from0 to INT_MAX) (default0)
-preset <int> E..V...... (from1 to 7) (default medium)
veryfast 7 E..V......
faster 6 E..V......
fast 5 E..V......
medium 4 E..V......
slow 3 E..V......
slower 2 E..V......
veryslow 1 E..V......
-rdo <int> E..V...... Enable rate distortion optimization (from-1 to 1) (default-1)
-max_frame_size <int> E..V...... Maximum encoded frame size in bytes (from-1 to 65535) (default-1)
-max_slice_size <int> E..V...... Maximum encoded slice size in bytes (from-1 to 65535) (default-1)
-bitrate_limit <int> E..V...... Toggle bitrate limitations (from-1 to 1) (default-1)
-mbbrc <int> E..V...... MB level bitrate control (from-1 to 1) (default-1)
-extbrc <int> E..V...... Extended bitrate control (from-1 to 1) (default-1)
-adaptive_i <int> E..V...... Adaptive I-frame placement (from-1 to 1) (default-1)
-adaptive_b <int> E..V...... Adaptive B-frame placement (from-1 to 1) (default-1)
-b_strategy <int> E..V...... Strategy to choose between I/P/B-frames (from-1 to 1) (default-1)
-forced_idr <boolean> E..V...... Forcing I frames as IDR frames (defaultfalse)
-low_power <boolean> E..V...... enable low power mode(experimental: many limitations by mfx version, BRC modes, etc.) (defaultfalse)
-cavlc <int> E..V...... Enable CAVLC (from0 to 1) (default0)
-idr_interval <int> E..V...... Distance (in I-frames) between IDR frames (from0 to INT_MAX) (default0)
-pic_timing_sei <int> E..V...... Insert picture timing SEI with pic_struct_syntax element (from0 to 1) (default1)
-single_sei_nal_unit <int> E..V...... Put all the SEI messages into one NALU (from-1 to 1) (default-1)
-max_dec_frame_buffering <int> E..V...... Maximum number of frames buffered in the DPB (from0 to 65535) (default0)
-look_ahead <int> E..V...... Use VBR algorithm with look ahead (from0 to 1) (default0)
-look_ahead_depth <int> E..V...... Depth of look ahead in number frames (from0 to 100) (default0)
-look_ahead_downsampling <int> E..V...... Downscaling factor for the frames saved for the lookahead analysis (from0 to 3) (default unknown)
unknown 0 E..V......
auto 0 E..V......
off 1 E..V......
2x 2 E..V......
4x 3 E..V......
-int_ref_type <int> E..V...... Intra refresh type (from-1 to 65535) (default-1)
none 0 E..V......
vertical 1 E..V......
-int_ref_cycle_size <int> E..V...... Number of frames in the intra refresh cycle (from-1 to 65535) (default-1)
-int_ref_qp_delta <int> E..V...... QP difference for the refresh MBs (from-32768 to 32767) (default-32768)
-recovery_point_sei <int> E..V...... Insert recovery point SEI messages (from-1 to 1) (default-1)
-profile <int> E..V...... (from0 to INT_MAX) (default unknown)
unknown 0 E..V......
baseline 66 E..V......
main 77 E..V......
high 100 E..V......
-a53cc <int> E..V...... Use A53 Closed Captions (if available) (from0 to 1) (default1)
-aud <int> E..V...... Insert the Access Unit Delimiter NAL (from0 to 1) (default0)
-mfmode <int> E..V...... Multi-Frame Mode (from0 to 2) (default auto)
off 1 E..V......
auto 2 E..V......
-repeat_pps <boolean> E..V...... repeat pps for every frame (defaultfalse)
また、-vfオプションの中で指定できる項目(フィルター)は、以下の3つとなっている。
- vpp_qsv
- scale_qsv
- overlay_qsv
- deinterlace_qsv
それぞれのフィルタの詳細は、ffmpeg -h filter=vpp_qsv
等と指定することでで確認出来る。
QSVでMPEG2をH.264にトランスコードしてみる
基本的にMPEG2からH.264へ変換する場合の例は次のような形になる。MPEG2のデコードからQSVへ明示的に流してあげる形をとらないと、デコードがソフトウェアで行われてしまう。
ffmpeg-hwaccelqsv-c:vmpeg2_qsv-i[input]-c:vh264_qsv-vf'scale_qsv=1280:720'-q:v23-c:acopyoutput.mp4
q:v 23
は品質固定のCQPモード。数字が低いほど画質は高くなる(VAAPIでいう、qp
である)。こちらのサイトによれば、QSV対応ffmpegでは概ね23程度に設定をすると支障がないとのこと。
format=nv12
等は、先述のサイトによればffmpeg4からは原則として廃止されているとのことで、今回は外している。
あとは実際にやってみるのみ。先の設定で、15Mbpsほどある1080iのMPEG2(地デジ)の番組は17倍速程度、500fpsほどで処理され、3-4Mbpsまで縮んでいた。
ちなみに、同じ素材をVAAPIを用いて行うと、qp20の設定で11-12倍、360fpsくらい。速度は申し分なく、また(欲を言えばもう少しファイルサイズが小さくなって欲しいが)簡易なエンコード用途であれば十分だ。
Intel Media SDKを用いると、H265のエンコードも可能である。何日か使ってみて、おかしなところが出てこないか確かめておこうと思う。