#DebianでQSVで爆速エンコードしたい!※
この記事では
ffmpeg -hwaccel vaapi (VAAPI + i965) より 高スループット/高品質が狙える
ffmpeg -hwaccel qsv (libmfx + iHD) が使えるffmpegのビルドをまっさらなdebianで行います。
※mpeg2ts -> h.264 HWトランスコードが 9.53倍速くらい。 CPU使用率15%。
###そのまえに、、Ubuntuならもっと簡単です
Ubuntuの場合、依存ライブラリがパッケージ化されているのでもっと簡単です。
ビルドするのはffmpegだけがいい!という方はUbuntu使いましょう。
(ubuntuもパッケージ版ffmpegは --enable-libmfx されてないのでffmpegだけはビルド必要)
2020/06/19現在のパッケージ提供状況
Source | libmxf | libva | iHD |
---|---|---|---|
Ubuntu Package | 20.1.0 | 2.7.0 | 20.1.1 |
Debian Package | No Packgae | 2.4.0-1(too old) | 18.4.1(too old) |
github | 20.1.1 | 2.7.1 | 20.1.1 |
では、始めていきます。
##構成
###ソフトウェア
Debian は 2020年06月現在最新の 10.4.0(buster) amd64 で試しています。
ビルドが必要なもの以外はなるべくパッケージを使って楽する方針です。
現在 Debian10(buster) には、、
- Intel-Mdia-SDK がパッケージで提供されておらず、ビルドが必要です。
- libvaはPackage版 (バージョン 2.4.0-1 ) がIntel-Media-SDKの要件より古いため、ビルドが必要です。
- iHDドライバは[Package版] (https://packages.debian.org/buster/intel-media-va-driver)(18.4.1+dfsg1-1)が古すぎてちゃんと動かないためビルドが必要です。
種別 | ソフトウェア | バージョン | ソース |
---|---|---|---|
OS | Debian | 10.4.0-amd64 | |
VA-API | libva | 2.7.0 | github |
VA-API Driver | iHD_drv_video.so | 20.2.pre | github |
Intel-Mdia-SDK | msdk | 20.1.1 | github |
Va-API Util | vainfo | 2.4.0+ds1-1 | Package |
###ハードウェア
Intel Quick Sync Video (libmfx + iHD)を使ったハードウェアエンコード/デコードには、Core iシリーズでいえば第6世代以上が必要になります。この手順では第8世代のIntel Core i5を使って動作確認しています。
CPUごとの機能対応表は https://trac.ffmpeg.org/wiki/Hardware/QuickSync が詳しいです。
ハードウェア種別 | 名称 | 備考 |
---|---|---|
CPU | Intel(R) Core(TM) i5-8500 CPU @ 3.00GHz | Coffee Lake |
Memory | 8GB | PC4-21300 (2666MT/s) 8GBx1 |
#インストール手順
Debian新規にインストールし終わったところからスタート
###作業ユーザで sudoが 使えるようにします。
$ su -
# usermod -aG sudo daigo
# apt install sudo
# exit
$ exit
共通して使うビルドツールのインストール
#ビルドに共通して使用するパッケージをインストール
$ sudo apt install build-essential git cmake pkg-config
###libva (VA-API) のビルド、インストール、動作確認
#依存するパッケージのインストール
$ sudo apt install meson libdrm-dev automake libtool
#LibVAの最新版を取得
$ git clone https://github.com/intel/libva.git
$ cd libva
# ビルドとインストール。
$ ./autogen.sh
$ make
$ sudo make install
...(略)
Libraries have been installed in:
/usr/local/lib
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the 'LD_RUN_PATH' environment variable
during linking
- use the '-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to '/etc/ld.so.conf'
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
libvaがインストールされた /usr/local/lib はLD-PATHに含まれれないので、以下のコマンドで追加します。
これによって、"libva2 Package(バージョン 2.4.0-1 )" が/usr/lib にインストールされていても、今回インストールした最新版が優先して読み込まれます。
sudo sh -c "echo /usr/local/lib >> /etc/ld.so.conf.d/local.conf"
sudo ldconfig
ldconfigの効果の確認します。vainfo から参照される libvaが/usr/local/lib を指していることを確認します。
# vainfoをパッケージでインストール
$ sudo apt install vainfo
# vainfoが参照しているlibvaがビルドしたものであることを確認
$ ldd /usr/bin/vainfo | grep /usr/local/
libva-drm.so.2 => /usr/local/lib/libva-drm.so.2 (0x00007fe6f8bc4000)
libva.so.2 => /usr/local/lib/libva.so.2 (0x00007fe6f8b95000)
この段階で、vainfoコマンドでVA-APIの状況を確認してみます。
まだVA-APIドライバが所定の場所に置かれてないのでドライバが開けないとエラーが出ます。
# vainfoを実行してもドライバがないのでエラーになる
$ vainfo
error: can't connect to X server!
libva info: VA-API version 1.8.0
libva info: Trying to open /usr/local/lib/dri/iHD_drv_video.so
libva info: va_openDriver() returns -1
libva info: Trying to open /usr/local/lib/dri/i965_drv_video.so
libva info: va_openDriver() returns -1
vaInitialize failed with error code -1 (unknown libva error),exit
###VA-APIドライバ(iHD_drv_video.so)のビルドとインストール
iHD_drv_video.so をビルドしていきます。
#依存パッケージのインストール
sudo apt install libpciaccess-dev
#依存ライブラリ(Intel(R) Graphics Memory Management Library)のビルド
$ cd
$ git clone https://github.com/intel/gmmlib
$ cd gmmlib/
$ mkdir build && cd build
$ cmake ..
$ make
#VA-APIドライバ(iHD_drv_video.so)のビルド
$ cd
$ git clone https://github.com/intel/media-driver
$ mkdir build_media
$ cd build_media/
$ cmake ../media-driver
$ make
$ sudo make inatall
ここまでくれば vainfo コマンドで新しいドライバが認識されるはずですので確認します。
# vainfoを実行
$ sudo vainfo
error: can't connect to X server!
libva info: VA-API version 1.8.0
libva info: Trying to open /usr/local/lib/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_8
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.8 (libva 2.4.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 20.2.pre (3640b64c)
vainfo: Supported profile and entrypoints
VAProfileNone : VAEntrypointVideoProc
VAProfileNone : VAEntrypointStats
VAProfileMPEG2Simple : VAEntrypointVLD
VAProfileMPEG2Simple : VAEntrypointEncSlice
VAProfileMPEG2Main : VAEntrypointVLD
VAProfileMPEG2Main : VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointFEI
VAProfileH264Main : VAEntrypointEncSliceLP
VAProfileH264High : VAEntrypointVLD
VAProfileH264High : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointFEI
VAProfileH264High : VAEntrypointEncSliceLP
VAProfileVC1Simple : VAEntrypointVLD
VAProfileVC1Main : VAEntrypointVLD
VAProfileVC1Advanced : VAEntrypointVLD
VAProfileJPEGBaseline : VAEntrypointVLD
VAProfileJPEGBaseline : VAEntrypointEncPicture
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointFEI
VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
VAProfileVP8Version0_3 : VAEntrypointVLD
VAProfileVP8Version0_3 : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointFEI
VAProfileHEVCMain10 : VAEntrypointVLD
VAProfileHEVCMain10 : VAEntrypointEncSlice
VAProfileVP9Profile0 : VAEntrypointVLD
VAProfileVP9Profile2 : VAEntrypointVLD```
やりました。これで Media SDKに必要なVA-API(libva)の最新版とドライバの最新版が導入できました。
Media SDKのビルド、インストール
gitから Media SDKをダウンロードし、ビルド、インストールしていきます。
ビルドフラグ、およびインストール先が途中表示されますので確認しておきます。
# git からMediaSDKをダウンロード
$ git clone https://github.com/Intel-Media-SDK/MediaSDK msdk
$ cd msdk
# ビルドフォルダを作る
$ mkdir build && cd build
# cmake を実行。ビルドフラグが最後に表示される。
$ cmake ..
...(略)...
Release flags:
CMAKE_C_FLAGS_RELEASE : -O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE : -O3 -DNDEBUG
Debug flags:
CMAKE_C_FLAGS_DEBUG : -g -D_DEBUG
CMAKE_CXX_FLAGS_DEBUG : -g -D_DEBUG
Install:
CMAKE_INSTALL_PREFIX : /opt/intel/mediasdk
CMAKE_INSTALL_FULL_INCLUDEDIR : /opt/intel/mediasdk/include
CMAKE_INSTALL_FULL_LIBDIR : /opt/intel/mediasdk/lib
CMAKE_INSTALL_FULL_DATADIR : /opt/intel/mediasdk/share
Enable:
ENABLE_OPENCL : ON
ENABLE_X11 : OFF
ENABLE_X11_DRI3 : OFF
ENABLE_WAYLAND : OFF
ENABLE_ITT : OFF
ENABLE_TEXTLOG : OFF
ENABLE_STAT : OFF
Build:
BUILD_RUNTIME : ON
BUILD_DISPATCHER : ON
BUILD_SAMPLES : ON
BUILD_TUTORIALS : ON
BUILD_TESTS : OFF
BUILD_TOOLS : OFF
BUILD_KERNELS : OFF
...(略)...
# make & mke install 。インストール先を確認。
$ make
$ sudo make install
...(略)...
-- Install configuration: "release"
-- Installing: /opt/intel/mediasdk/share/mfx/plugins.cfg
-- Installing: /opt/intel/mediasdk/lib/libmfx.so.1.32
-- Installing: /opt/intel/mediasdk/lib/libmfx.so.1
-- Installing: /opt/intel/mediasdk/lib/libmfx.so
-- Installing: /opt/intel/mediasdk/lib/pkgconfig/libmfx.pc
-- Installing: /opt/intel/mediasdk/include/mfx
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvideo++.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxpcp.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvstructures.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxcommon.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxla.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxastructures.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxplugin.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxscd.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxaudio++.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxpak.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxaudio.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxadapter.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxdefs.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxplugin++.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvp8.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvideo.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxjpeg.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxfeihevc.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxsession.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxfei.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxdispatcherprefixedfunctions.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvp9.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxstructures.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxbrc.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxenc.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxcamera.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxsc.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxmvc.h
-- Installing: /opt/intel/mediasdk/lib/pkgconfig/mfx.pc
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_decode
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_encode
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_fei
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_hevc_fei
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_hevc_fei_abr
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_vpp
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_multi_transcode
-- Installing: /opt/intel/mediasdk/share/mfx/samples/libsample_rotate_plugin.so
-- Installing: /opt/intel/mediasdk/share/mfx/samples/libvpp_plugin.a
-- Installing: /opt/intel/mediasdk/share/mfx/samples/libcttmetrics.so
-- Installing: /opt/intel/mediasdk/share/mfx/samples/metrics_monitor
-- Installing: /opt/intel/mediasdk/lib/libmfxhw64.so.1.32
-- Installing: /opt/intel/mediasdk/lib/libmfxhw64.so.1
-- Installing: /opt/intel/mediasdk/lib/libmfxhw64.so
-- Installing: /opt/intel/mediasdk/lib/pkgconfig/libmfxhw64.pc
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_hevce_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_hevc_fei_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_vp9e_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_h264la_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_hevcd_hw64.so
-- Up-to-date: /opt/intel/mediasdk/lib/mfx/libmfx_hevcd_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_vp8d_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_vp9d_hw64.so
$ cd
mediasdkがインストールされた /opt/intel/mediasdk/lib はLD-PATHに含まれれないので、以下のコマンドで追加します。
$ sudo sh -c "echo /opt/intel/mediasdk/lib/ >> /etc/ld.so.conf.d/mediasdk.conf"
$ sudo ldconfig
ffmpegのビルド
いよいよ ffmpegをビルドします。
#libfdk-aac のために non-freeレポジトリを加える必要がある。
$ sudo apt install software-properties-common
$ sudo apt-add-repository non-free
#依存パッケージのインストール
$ sudo apt update -qq && sudo apt -y install \
autoconf \
automake \
build-essential \
cmake \
git-core \
libass-dev \
libfreetype6-dev \
libgnutls28-dev \
libsdl2-dev \
libtool \
libva-dev \
libvdpau-dev \
libvorbis-dev \
libxcb1-dev \
libxcb-shm0-dev \
libxcb-xfixes0-dev \
pkg-config \
texinfo \
wget \
yasm \
zlib1g-dev \
nasm \
libx264-dev \
libx265-dev libnuma-dev \
libvpx-dev \
libfdk-aac-dev \
libmp3lame-dev \
libopus-dev \
libaom-dev
# mediasdk の lib や include の位置を示す pkgconfig が非標準の場所にあるため、
# このままだとConfigureで場所が解決できない。環境変数で参照を追加してやる。
$ export PKG_CONFIG_PATH=/opt/intel/mediasdk/lib/pkgconfig:$PKG_CONFIG_PATH
# ffmpegのソースのダウンロードとビルド、インストール
$ cd
$ wget -O ffmpeg-snapshot.tar.bz2 https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
$ tar xjvf ffmpeg-snapshot.tar.bz2
$ cd ffmpeg
$ ./configure \
--extra-libs="-lpthread -lm" \
--enable-libmfx \
--enable-gpl \
--enable-gnutls \
--enable-libaom \
--enable-libass \
--enable-libfdk-aac \
--enable-libfreetype \
--enable-libmp3lame \
--enable-libopus \
--enable-libvorbis \
--enable-libvpx \
--enable-libx264 \
--enable-libx265 \
--enable-nonfree
$ make
$ sudo make install
これでffmpegのインストールが完了しました。
動作テスト
###インストールしたffmpegの確認
ビルドしたlibmfxを参照していることを確認します。
また、エンコーダー、デコーダ一覧を表示して QSV対応コーデックがリストされることを確認します。
# mediasdk を参照していることの確認
daigo@epgstation:~$ ldd /usr/local/bin/ffmpeg | grep /opt
libmfx.so.1 => /opt/intel/mediasdk/lib/libmfx.so.1 (0x00007f44af339000)
# QSVを使ったデコーダがリストされることの確認
$ ffmpeg -decoders|grep qsv
V....D h264_qsv H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration) (codec h264)
V....D hevc_qsv HEVC (Intel Quick Sync Video acceleration) (codec hevc)
V....D mjpeg_qsv MJPEG video (Intel Quick Sync Video acceleration) (codec mjpeg)
V....D mpeg2_qsv MPEG-2 video (Intel Quick Sync Video acceleration) (codec mpeg2video)
V....D vc1_qsv VC-1 video (Intel Quick Sync Video acceleration) (codec vc1)
V....D vp8_qsv VP8 video (Intel Quick Sync Video acceleration) (codec vp8)
V....D vp9_qsv VP9 video (Intel Quick Sync Video acceleration) (codec vp9)
# QSVを使ったエンコーダがリストされることの確認
$ ffmpeg -encoders|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)
V..... vp9_qsv VP9 video (Intel Quick Sync Video acceleration) (codec vp9)
###ちょっくら録画したアニメをエンコードしてみる。→ 9.53倍速
9.53倍速でエンコード完了。CPU使用率は高々16%前後。
※この時なぜかsudoしないとデバイスが開けないと怒られました。。video groupには加えてみたのですが改善せず。。
ちょっとよくわからない。。
# アニメ 30分番組 の mpeg2tsを h.264 へトランスコード。
$ sudo ffmpeg -y -hwaccel qsv -c:v mpeg2_qsv -i input.ts -c:v h264_qsv -global_quality 25 -acodec copy output.mp4
.........
frame=54092 fps=285 q=26.0 Lsize= 417871kB time=00:30:04.76 bitrate=1896.8kbits/s dup=5222 drop=0 speed=9.53x
video:360246kB audio:56376kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.299822%
# 9.53倍速でエンコード完了
6並列でエンコードしてみる。→ 2.00 倍速
興味本位で6並列でエンコードしてみました。
結果、ちょうど2x 倍速でエンコードが終了しました。
# アニメ 30分番組 の mpeg2tsを h.264 へトランスコード。 x6プロセス
$ seq 1 1 6 | parallel -j 6 sudo ffmpeg -y -hwaccel qsv -c:v mpeg2_qsv -i input.ts -c:v h264_qsv -global_quality 25 -acodec copy output{}.mp4
.........
frame=54092 fps= 60 q=26.0 Lsize= 417871kB time=00:30:04.76 bitrate=1896.8kbits/s dup=5222 drop=0 speed= 2x
video:360246kB audio:56376kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.299822%
###システム負荷を見てみる。
1プロセス | 6プロセス | |
---|---|---|
ロードアベレージ | 0.75 | 1.20 |
CPU使用率 | 20%前後 | 60%前後 |
メモリ VSZ | 800.076MB | 528.172MB* 6 |
メモリ RSS | 92.572MB | 67.824MB * 6 |
トランスコード速度 | 9.53x | 2x |
単純にFFMPEGを並走させるだけの場合、CPU system time / user time は同じリソースを食い合うような動きになるようです。 iowait timeだけプロセス分増えているような格好になってます。
並列させても iowait だけが上がり、load averageはほとんど影響を受けないようです。
実質的なメモリ使用率もだいぶ低い印象。
これくらいの負荷なら、録画プロセスへの影響も特段気にせずにガンガンエンコードできそうです。よかったです(小並感)。
##参照した公式ドキュメント
Build Media SDK on Ubuntu (Intel-Media-SDK)
手順上の変更点
- LD_LIBRARY_PATHに /usr/local/lib を追加する手順を加えています。
- LD_LIBRARY_PATHに /opt/intel/mediasdk/lib/ を追加する手順を加えています。
Compile FFmpeg for Ubuntu, Debian, or Mint
手順上の変更点
- ビルドの際のフォルダの使い方をより単純にしています。
- 今回の本題、QSVに対応させるために --enable-libxmf の追加しています。
- liboam はソースからのビルドでなくパッケージを使ってます。
- gnutlsパッケージが--pkg-config-flags="--static" に対応してなったので--pkg-config-flags="--static" を削除しています。
Hardware/QuickSync – FFmpeg
https://trac.ffmpeg.org/wiki/Hardware/QuickSync
概要説明や動作確認用のコマンドを参考にしています。