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

関連記事

他のサイト

基本となるファイル

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,vpp_qsv=1280:720,hwdownload,format=nv12,fps=30000/1001,decimate -r 24000/1001 -c:v h264_qsv -g 240 -look_ahead 0 -q:v 20 -c:a copy out.mp4

‘corrupt input packet in stream 1’ error in FFMPEG – Stack Overflow

以下のエラーが出る場合は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 リサイズフィルタの利用例。scale_qsvフィルタはvpp_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,vpp_qsv=w=1280:h=720 -c:v h264_qsv -g 240 -q:v 20 -c:a copy out.mp4

メインディスプレイは外部GPUから、サブディスプレイはintel GPUをつなげているときにQSVが使えないときはchild_deviceの番号を0以外にする。
ffmpeg -init_hw_device qsv:1,child_device_type=d3d11va -i input.h264

Anyway to select GPU on QSV encoder? : ffmpeg
lavfi: add hwdevice flag to hwupload/hwmap · FFmpeg/FFmpeg@9bf1848 · GitHub

Windows 以外の環境
centos7でffmpeg h264_qsv感想など。 : archive.org

h264_qsvエンコーダの設定

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

エンコーダオプションの既定値。
FFmpeg/qsvenc_h264.c at master · FFmpeg/FFmpeg

  • -refs:0
  • -g:250
  • -bf:3
  • -qmin:-1
  • -qmax:-1
  • -trellis:-1
  • -flags:+cgop

実行コマンド例

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

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

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

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

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

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

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

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

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

addroiフィルタに対応した。ffmpeg 5.1からの予定
映像の特定領域だけ品質を変える addroi

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

HD未満
ffmpeg -i input -c:v h264_qsv -g 240 -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 -g 240 -look_ahead 0 -b:v 2000k -maxrate 2000k -color_primaries bt709 -color_trc bt709 -colorspace bt709 -color_range tv -c:a copy output.mp4

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

HD未満
ffmpeg -i input -c:v h264_qsv -g 240 -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 -g 240 -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 -bsf:v h264_metadata=colour_primaries=6:transfer_characteristics=6:matrix_coefficients=6 -c copy output.mp4

HD以上
ffmpeg -i input -bsf:v h264_metadata=colour_primaries=1:transfer_characteristics=1:matrix_coefficients=1 -c copy output.mp4

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

hevc_qsvエンコーダの設定

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

エンコーダオプションの既定値。
FFmpeg/qsvenc_hevc.c at master · FFmpeg/FFmpeg

  • -refs:0
  • -g:248
  • -bf:-1
  • -qmin:-1
  • -qmax:-1
  • -trellis:-1
  • -flags:+cgop

実行コマンド例

-gpbを無効にするとPフレームが挿入されるようになる。既定値の1だとI、Bフレームしかない。既定値のPフレームなしがよいのか判断できていない。もしかしてほかの設定が必要かも。ビットレートや品質指定はh264_qsvを参考にする。

ffmpeg -i input -c:v hevc_qsv -gpb 0 -bf 2 -refs 3 -g 240 -load_plugin hevc_hw -preset:v faster output.mp4

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

HD未満
ffmpeg -i input -c:v hevc_qsv -gpb 0 -bf 2 -refs 3 -g 240 -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 -gpb 0 -bf 2 -refs 3 -g 240 -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

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

HD未満
ffmpeg -i input -c:v hevc_qsv -gpb 0 -bf 2 -refs 3 -g 240 -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 -gpb 0 -bf 2 -refs 3 -g 240 -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 -bsf:v hevc_metadata=colour_primaries=6:transfer_characteristics=6:matrix_coefficients=6 -c copy output.mp4

HD以上
ffmpeg -i input -bsf:v hevc_metadata=colour_primaries=1:transfer_characteristics=1:matrix_coefficients=1 -c copy output.mp4

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

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 vpp_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,vpp_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=w=1280:h=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,vpp_qsv=w=1280:h=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から使えるエンコーダ。

ffmpeg -h encoder=vp9_qsv

実行コマンド例

ffmpeg -init_hw_device qsv=qsv -hwaccel qsv -i input -vf hwupload=extra_hw_frames=64,format=qsv -c:v vp9_qsv -async_depth 8 -low_power true -preset veryslow output.mp4

vp9_qsv vs libvpx-vp9 file seek and open times : ffmpeg

av1_qsvエンコーダの設定

ffmpeg 5.2から使える予定のエンコーダ。DG2/Alchemist GPUが必要で、Arc Graphics A380、A750、A770モデルが対応する。

ffmpeg -h encoder=av1_qsv

QSVデコーダを使う

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

デコーダ一覧。対応世代はWikipediaを参照

  • h264_qsv
  • mjpeg_qsv
  • mpeg2_qsv
  • hevc_qsv
  • vc1_qsv
  • vp8_qsv
  • vp9_qsv
  • av1_qsv(Tiger Lake、11世代以降)

デコーダオプション

  • -async_depth[int]
    内部並列化の深さ。大きな値ほど遅延も増える
    既定値:4
    範囲:1からINT_MAXまで
  • -gpu_copy[int]
    システムメモリからGPUへコピーする。通常は無指定でもコピーする。無効にすると処理が遅くなる
    • 0, default:既定値
    • 1, on
    • 2, off

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

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以降)、vpp_qsvに統合(6.0以降?)
  • 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,vpp_qsv=w=1280:h=720 -c:v h264_qsv -g 240 -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,vpp_qsv=w=1280:h=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,vpp_qsv=w=1280:h=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,vpp_qsv=w=1280:h=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,vpp_qsv=w=1280:h=720 -c:v h264_qsv -g 240 -c:a copy output.mp4

3 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.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

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