ffmpeg で使える QSV(Intel Quick Sync Video)のビルド方法と使い方。CPU の世代によって使えるエンコーダ、デコーダ、オプションやフィルタが異なる。

関連記事

他のサイト
This gist will generate an Intel QSV-enabled FFmpeg build using the open source Intel Media SDK. Testbed used: Ubuntu 18.04LTS. A fallback is also provided for the intel vaapi driver where needed.

基本となるファイル

Windows XPでも使えるffmpegはこちらで配布している。
FFmpegダウンロード お気に入りの動画を携帯で見よう

ffmpeg をつくる

Windows 環境ならmedia-autobuild_suiteを使うのが楽。--enable-libmfxを指定する。

エラーの回避方法

以下のようなエラーが出る場合は-look_ahead 0をつける。現在は既定値が 0 になっているので設定する必要はない。

More than one of: { constant qscale, lookahead, VCM } requested, only one of them can be used at a time.Error initializing output stream 0:0 — Error while opening encoder for output stream #0:0 – maybe incorrect parameters such as bit_rate, rate, width or height

以下のようなエラーが出る場合は-init_hw_device qsv:hwをつける。
https://trac.ffmpeg.org/ticket/6492より。
詳しくはhttps://ffmpeg.org/ffmpeg-all.html#Advanced-Video-options

No device available for encoder (device type qsv for codec h264_qsv).

Selected ratecontrol mode is not supported by the QSV runtime. Choose a different mode.
Error initializing output stream 0:0 — Error while opening encoder for output stream #0:0 – maybe incorrect parameters such as bit_rate, rate, width or height

逆に、付けるとエラーになる場合-init_hw_device qsv:hwを外す。
https://trac.ffmpeg.org/ticket/6827より。

Failed to create Direct3D device
Device creation failed: -1313558101.
Failed to set value ‘qsv:hw’ for option ‘init_hw_device’: Unknown error occurred

以下のようなエラーが出る場合は読み込み時のバッファを増やす。

Decoding pixel format ‘(null)’ is not supported
Error while decoding stream #0:0: Function not implemented

ffmpeg -analyzeduration 30M -probesize 30M -i input.ts -c copy output.ts

またドロップしたフレームがあり読み込みに失敗するときには、それを読み込まない入力オプション-fflags +discardcorruptを付ける方法もある。以下は QSV フィルタの併用例。

ffmpeg -hwaccel qsv -c:v mpeg2_qsv -fflags +discardcorrupt -analyzeduration 30M -probesize 30M -i input.ts -vf deinterlace_qsv,scale_qsv=1280:720,hwdownload,format=nv12,fps=30000/1001,decimate -r 24000/1001 -c:v h264_qsv -look_ahead 0 -q:v 20 -c:a copy out.mp4

以下のエラーが出る場合はhwuploadフィルタをつける。

The input must have a hardware frame reference.

以下のエラーが出る場合はhwuploadフィルタのフレーム数を増やす。

Error while filtering: Cannot allocate memory
Failed to inject frame into filter network: Cannot allocate memory
Error while processing the decoded data for stream #0:0

QSV リサイズフィルタの利用例。
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -fflags +discardcorrupt -i input.mp4 -vf hwupload=extra_hw_frames=10,scale_qsv=1280:720 -c:v h264_qsv -q:v 20 -c:a copy out.mp4

Windows 以外の環境
centos7でffmpeg h264_qsv感想など。

実行コマンド例

CBR(固定ビットレート):ffmpeg -i input -c:v h264_qsv -look_ahead 0 -b:v 2000k -maxrate 2000k -c:a copy output.mp4

VBR(可変ビットレート):ffmpeg -i input -c:v h264_qsv -look_ahead 0 -b:v 4000k -c:a copy output.mp4

VBR+look_ahead(可変ビットレート):ffmpeg -i input -c:v h264_qsv -look_ahead 1 -b:v 4000k -c:a copy output.mp4

CQP(品質指定):ffmpeg -i input -c:v h264_qsv -look_ahead 0 -q:v 20 -c:a copy output.mp4

ニコ生のように制限ビットレートがある場合は VBR にすることで制限できる。CQP のビットレートは配信映像に依存するので使い慣れればこちらでも良い。品質指定は数値が小さいほど高ビットレートになる。

ICQ(品質指定):ffmpeg -i input -c:v h264_qsv -look_ahead 0 -global_quality 20 -c:a copy output.mp4

ICQ+look_ahead(品質指定):ffmpeg -i input -c:v h264_qsv -look_ahead 1 -look_ahead_depth 30 -global_quality 20 -c:a copy output.mp4

-look_aheadを有効にし-look_ahead_depthで先読みするフレーム数を指定することでフレーム毎に最適な品質を選び圧縮率を高める。ただしこの値が高いとライブ配信における遅延が指定フレーム数だけ増える。

-presetは遅くなるほどフレームの品質が上がりサイズも増える傾向にあり、veryfastveryslowでは2倍くらい処理速度が違う。

カラースペースなどを明示するビットストリームフィルタを指定する。
ビットストリームフィルタのまとめ

HD未満
ffmpeg -i input -c:v h264_qsv -look_ahead 0 -b:v 2000k -maxrate 2000k -bsf:v h264_metadata=colour_primaries=6:transfer_characteristics=6:matrix_coefficients=6 -c:a copy output.mp4

HD以上
ffmpeg -i input -c:v h264_qsv -look_ahead 0 -b:v 2000k -maxrate 2000k -bsf:v h264_metadata=colour_primaries=1:transfer_characteristics=1:matrix_coefficients=1 -c:a copy output.mp4

カラースペースなどの入力、出力オプションを指定する。
色の情報の扱いについて

HD未満
ffmpeg -i input -c:v h264_qsv -look_ahead 0 -b:v 2000k -maxrate 2000k -color_primaries smpte170m -color_trc smpte170m -colorspace smpte170m -color_range -c:a copy output.mp4

HD以上
ffmpeg -i input -c:v h264_qsv -look_ahead 0 -b:v 2000k -maxrate 2000k -color_primaries bt709 -color_trc bt709 -colorspace bt709 -color_range tv -c:a copy output.mp4

h264_qsv エンコーダの設定

ffmpeg -h encoder=h264_qsvで見られるエンコード設定とエンコーダ全般に指定できる設定の2つがある。

エンコーダオプションの既定値。

  • -refs:0
  • -g:250
  • -bf:3
  • -qmin:-1
  • -qmax:-1

公式ドキュメント:FFmpeg Codecs Documentation : QSV-encoders

hevc_qsv エンコーダの設定

Kaby Lake(第7世代)CPU 以降であればhevc_qsvエンコーダが使える。
ffmpeg -h encoder=hevc_qsv

エンコーダオプションの既定値。

  • -refs:0
  • -g:248
  • -bf:8
  • -qmin:-1
  • -qmax:-1

コマンド例
ffmpeg -i input -c:v hevc_qsv -load_plugin hevc_hw -preset:v faster output.mkv

カラースペースなどを明示するビットストリームフィルタを指定する。
ビットストリームフィルタのまとめ

HD未満
ffmpeg -i input -c:v hevc_qsv -load_plugin hevc_hw -b:v 2000k -maxrate 2000k -bsf:v hevc_metadata=colour_primaries=6:transfer_characteristics=6:matrix_coefficients=6 -c:a copy output.mp4

HD以上
ffmpeg -i input -c:v hevc_qsv -load_plugin hevc_hw -b:v 2000k -maxrate 2000k -bsf:v hevc_metadata=colour_primaries=1:transfer_characteristics=1:matrix_coefficients=1 -c:a copy output.mp4

カラースペースなどの入力、出力オプションを指定する。
色の情報の扱いについて

HD未満
ffmpeg -i input -c:v hevc_qsv -load_plugin hevc_hw -b:v 2000k -maxrate 2000k -color_primaries smpte170m -color_trc smpte170m -colorspace smpte170m -color_range -c:a copy output.mp4

HD以上
ffmpeg -i input -c:v hevc_qsv -load_plugin hevc_hw -b:v 2000k -maxrate 2000k -color_primaries bt709 -color_trc bt709 -colorspace bt709 -color_range tv -c:a copy output.mp4

mjpeg_qsv エンコーダの設定

Haswell(第4世代)CPU 以降であればmjpeg_qsvが使える。対応ピクセルフォーマットはnv12(4:2:0のこと)、qsv。-vframesで出力フレーム数を制限できる。-vsync 0で重複フレームを出力させなくしているがつけなくてもいいかもしれない。通常のフィルタとQSVフィルタを使い分けた例を併記。

ハードウェアデコーダ、フィルタ、エンコーダを組み合わせる

ffmpeg -h encoder=mjpeg_qsv

-global_quality[int]
品質指定。100に近いほど大容量高画質。
既定値:80

コマンド例。フィルタを当てる順番に注意。
ffmpeg -hwaccel qsv -c:v h264_qsv -i video.mp4 -c:v mjpeg_qsv -global_quality 80 -vframes 10 -vsync 0 img-%03d.jpg
ffmpeg -hwaccel qsv -c:v h264_qsv -i video.mp4 -vf hwdownload,format=nv12,scale=1280:720,hwupload=extra_hw_frames=64 -c:v mjpeg_qsv -global_quality 80 -vframes 10 -vsync 0 img-%03d.jpg
ffmpeg -hwaccel qsv -c:v h264_qsv -i video.mp4 -vf scale_qsv=1280:720 -c:v mjpeg_qsv -global_quality 80 -vframes 10 -vsync 0 img-%03d.jpg

通常は品質指定しなくても最適な品質を選ぶ。
ffmpeg -hwaccel qsv -c:v h264_qsv -i video.mp4 -c:v mjpeg_qsv -vsync 0 img-%03d.jpg

ハードウェア支援でデコードする例。
ffmpeg -hwaccel dxva2 -hwaccel_output_format dxva2_vld -i input -vf hwmap=derive_device=qsv,scale_qsv=1280:720 -c:v mjpeg_qsv -vsync 0 img-%03d.jpg

デコーダを指定しない例。フィルタを当てる順番に注意。
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -i input -vf scale=1280:720,hwupload=extra_hw_frames=64 -c:v mjpeg_qsv -vsync 0 img-%03d.jpg
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -i input -vf hwupload=extra_hw_frames=64,scale_qsv=1280:720 -c:v mjpeg_qsv -vsync 0 img-%03d.jpg

-f dshowなどのリアルタイムで映像を入力するときにmjpeg_qsvを使ってもCPU負荷はmjpeg_qsvを使わないときと同様に高いままである。

コマンド例。
ffmpeg -rtbufsize 10MB -video_size 1280x720 -framerate 60 -f dshow -i video="SCFF DirectShow Filter" -c:v mjpeg_qsv -vsync 0 img-%03d.jpg

vp9_qsv エンコーダの設定

ffmpeg 4.3(予定)から使えるエンコーダ。対応CPUは Ice Lake(10世代)で、Ubuntu の VAAPI 経由なので Windows では使えない。

ffmpeg -h encoder=vp9_qsv

QSV デコーダを使う

ハードウェアデコードは再生時のデコードを目的としていて、最新の CPU のソフトウェアデコードよりも高速ではない。 さらに通常デコードされたフレームを GPUメモリからシステムメモリにコピーする必要があり、その結果パフォーマンスがさらに低下する。考えられる用途は CPU をなるべく使いたくなかったり、リアルタイム配信、速度を重視しない場合などである。

デコーダ一覧

  • h264_qsv
  • mjpeg_qsv
  • mpeg2_qsv
  • hevc_qsv
  • vc1_qsv
  • vp8_qsv
  • vp9_qsv

CPU をフル活用してエンコードする場合、デコードの CPU 負荷を減らしその分をエンコードに使うことで速度の向上の可能性がある。

デコーダの部分についてコメントをいただいていたが、サーバのアカウント削除によりデータベースの保存が間に合わなかったのでコメントが消えてしまった。申し訳ない。

追記 2015年7月29日
デコーダも追加された。他にも HEVC、H264 も追加されている。
avcodec: Add QSV MPEG-2 video decoder :: git.videolan.org Git – ffmpeg.git/commitdiff
avcodec: Add QSV VC-1 video decoder :: git.videolan.org Git – ffmpeg.git/commitdiff

無指定だとソフトウェアデコードになるので、入力の前にデコーダを指定。
ffmpeg -c:v h264_qsv -i input

hevc の場合。
ffmpeg -c:v hevc_qsv -i input

ffplay の場合。
ffplay -codec:v h264_qsv -i input

デコーダはffmpeg -decoders > decoders.txtで一覧をテキストで見ることができる。

QSV フィルタを使う

ffmpeg 3.3 からデインターレーサとリサイザが追加された。ただし ffmpeg で使えても ffplay では使えないのでプレビュー用途なら標準出力して ffplay に渡す。また入力ファイルに応じて QSV デコーダを使わないと QSV フィルタが使えない-filter_hw_device qsvhwuploadフィルタでフレーム数を増やせば QSV デコーダを使わなくてもよい。ffmpeg 4.0 以降はフィルタのhwdownload,format=nv12が不要になり付けない方が高速になった。ただし例外が2つあり普通のフィルタに切り替えるときはhwdownload,format=nv12を挟み、ソフトウェアエンコーダを使うときはフィルタの最後にhwdownload,format=nv12をつける。

参考記事
This gist will generate an Intel QSV-enabled FFmpeg build using the open source Intel Media SDK. Testbed used: Ubuntu 18.04LTS. A fallback is also provided for the intel vaapi driver where needed. · GitHub

使えるフィルタ一覧

  • vpp_qsv(3.4以降)
  • scale_qsv(3.3以降)
  • overlay_qsv(4.0以降)
  • deinterlace_qsv(3.4以降)

vpp_qsvフィルタは第3世代の Intel Core シリーズでは一部が使えてないprocampを有効にすると使える。これらのフィルタは公式ドキュメントに記載がないのでコマンドからオプション内容を調べる。
ffmpeg -h filter=vpp_qsv > vpp_qsv.txt

コマンド例は2つあり1行目が QSV のデコード、フィルタ、エンコードを併用し、2行目が QSV フィルタだけ当てている。

リサイズ。
ffmpeg -hwaccel qsv -c:v h264_qsv -i input.mp4 -vf hwupload=extra_hw_frames=10,scale_qsv=1280:720 -c:v h264_qsv -q:v 20 -c:a copy output.mp4
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -i input.mp4 -vf hwupload=extra_hw_frames=10,scale_qsv=1280:720,hwdownload,format=nv12 -c:v libx264 -c:a copy output.mp4

デインターレース(bob になる)。QSV のデコードとインターレース解除を併用すると映像が乱れるのでコマンド例がない。
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -fflags +discardcorrupt -analyzeduration 30M -probesize 30M -i input.ts -vf hwupload=extra_hw_frames=64,deinterlace_qsv,hwdownload,format=nv12 -c:v libx264 -c:a copy output.mp4

TS ファイルをデインターレースとリサイズし、重複フレームを間引く(30p)。
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -fflags +discardcorrupt -analyzeduration 30M -probesize 30M -i input.ts -vf hwupload=extra_hw_frames=64,deinterlace_qsv,scale_qsv=1280:720,hwdownload,format=nv12,fps=30000/1001 -c:v libx264 -c:a copy output.mp4

TS ファイルをデインターレースとリサイズし、重複フレームを間引く(30p->24p)。
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -fflags +discardcorrupt -analyzeduration 30M -probesize 30M -i input.ts -vf hwupload=extra_hw_frames=64,deinterlace_qsv,scale_qsv=1280:720,hwdownload,format=nv12,fps=30000/1001,decimate -r 24000/1001 -c:v libx264 -c:a copy output.mp4

動画に動画をオーバーレイ。
ffmpeg -hwaccel qsv -c:v h264_qsv -i bgv.mp4 -c:v h264_qsv -i overlay.mp4 -filter_complex [0:v]hwupload=extra_hw_frames=10[0v];[1:v]hwupload=extra_hw_frames=10,[0v]overlay_qsv -c:v h264_qsv -q:v 20 -c:a copy output.mp4
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -i bgv.mp4 -i overlay.mp4 -filter_complex [0:v]hwupload=extra_hw_frames=10[0v];[1:v]hwupload=extra_hw_frames=10,[0v]overlay_qsv -c:v libx264 -c:a copy output.mp4

画像をオーバーレイ。
ffmpeg -init_hw_device qsv=qsv:hw -hwaccel qsv -filter_hw_device qsv -i bgv.mp4 -loop 1 -i overlay.png -filter_complex "[0:v]format=nv12,hwupload=extra_hw_frames=10[0v];[1:v] format=nv12,hwupload=extra_hw_frames=10[1v];[0v][1v]overlay_qsv" -c:v libx264 -c:a copy output.mp4

DXVA デコーダを使って、QSV フィルタとエンコードを併用。
ffmpeg -hwaccel dxva2 -hwaccel_output_format dxva2_vld -i input.mp4 -vf hwmap=derive_device=qsv,scale_qsv=w=1280:h=720 -c:v h264_qsv -c:a copy output.mp4

2 thoughts on “QSV 対応の ffmpeg をつくる

  • Kenny Lam

    Sorry to violating “日本語が含まれない投稿は無視されますのでご注意ください” below, I can read a little にほんご but I can’t write it with confident.

    Thanks for your detailed guide on using qsv filters, that helped me a lot to get FFMPEG+QuickSync working 🙂

    Just a friendly sharing for utilizing QSV with Decoding+Scale+Encoding, we can now remove “hwdownload,format=nv12″ in video filter, like this sample on using scale_qsv

    ffmpeg -hwaccel qsv -vcodec h264_qsv -i input.mp4 -vf scale_qsv=1280:720 -fflags +discardcorrupt -vcodec h264_qsv -look_ahead 0 -q:v 20 -acodec copy out.mp4

    As a result, the h264_qsv(input decoder) will result video in pix_fmt=”qsv”, that doesn’t require hwdownload and convert to NV12 but go to the h264_qsv(output encoder) directly, the performance increase will be significant. Only worked on FFMPEG 4.0 and after.

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)