mpv * Linux でハードウェアビデオアクセラレーション

この話は

  • 各ビデオカードにはビデオエンコード/デコード支援チップが載っている
  • QSVとかUVDとかVCEとかNVENCとかNVDECとか名前がついてる
  • Linux的にはVDPAUとVA-APIというAPIがある
  • Nvidiaの場合はNVENC直 (NVDEC直も可)
  • CUDAを使ったCUVIDってのもある
  • mpvで再生支援するのが便利

っていうのは理解しているという前提で始まる。

それは、「結局渡すべきパラメータはなに?」って話である。 なお、VDPAU及びVA-APIは有効である前提で話す。それがわからない人はArchwikiへGo

はじめに

mpvを使うと非常に便利で、

$ mpv video.mp4

みたいな話なんだけれども、mpvには--hwdec--voというオプションがあり、ハードウェアビデオアクセラレーションを行う場合はこれらを指定する。

で、--hwdecは話としては簡単だ。ハードウェアデコーダを使うという話。つまりはコーデック的な話。

じゃ--voは? という話になるのだが、これは「ビデオ出力ドライバ」の指定。 なんじゃそら…という感じなのだけれど、「エンコードと描画レイヤーは別の話」みたいなことらしい。 だからSDLとか、Direct3Dとか出てくる。 YUVビデオとかそのまま書くんじゃないの?とかいう気持ちになったけれど、そんなことはないようで、「ハードウェアでデコードしたらハードウェアで書くところまでしないと効果なし」みたいな話になるようだ。

とはいえ、--vox11なんてすると凄まじくCPU負荷が増えてしまうし、xvを使う理由も全くない。 だから現実的な選択肢としては、vdpau, vaapi, gpuの3つだ。

試してみる

vdpau + vdpau

VDPAUでデコードしてVDPAUで出力する、というのは悪くないようだ。

ただし、この場合ポストプロセスはVDPAUでやることになる。 VDPAUはポストプロセスに対応しているからできるのだけど、一部使えなくなるものもある。例えば、ズームは効かなくなる。

vdpau + gpu

VDPAUで出力するよりも軽い。

そしてフィルタ等はすべて使える。

vaapi + vaapi

ちゃんとアクセラレーションが効いて軽くなるけれど、エフェクト、フィルタなどは一切使えなくなる。 マニュアルにも、だめなシステム向けだと書いてある。

vaapi + gpu

VA-APIだと--vogpu指定にすべきなようだ。

ちなみに、VDPAUだと--voを書かなくても十分アクセラレーションが効くのだけど、VA-APIの場合は--vo必須。

NVDEC / CUVID

--vogpu一択。ほかはそもそも使えない。

結局…?

Intel

alias mpv='mpv --hwdec=vaapi --vo=gpu,vaapi'

AMD, Nvidia (nvドライバ)

alias mpv='mpv --hwdec=vdpau --vo=gpu,vdpau'

Intel同様にVA-APIを使っても構わない。 ただ、再生だけを考えるならVDPAUのほうが少し良い感じがする。

nvドライバ環境でハードウェアビデオアクセラレーションすべきかどうか自体が疑問。

Nvidia (nvidiaドライバ)

alias mpv='mpv --hwdec=nvdec --vo=gpu --profile=gpu-hq'

NVDEC直のほうが速い。

gpu-hq

通常の--vo=gpuはフェイルセーフで、--profile=gpu-hqすると品質優先、とのことなのだけど、 試してみた限りでは、特にgpu-hqして問題になるケースは見つからなかったので、--profile=gpu-hqつけても良いかもしれない。

その場合はfallback用に指定しているvaapivdpauvoは必要ないというか、つけないほうが良い。

私の設定

alias mpvpau="mpv --loop-playlist=yes --hwdec=vdpau --vo=gpu --profile=gpu-hq --prefetch-playlist=yes --video-latency-hacks=yes --osd-font='Fira Sans' --osd-font-size=23 --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5 --script=playlistmanager --script-opts=playlistmanager-loadfiles_on_start=yes"
alias mpvva="mpv --loop-playlist=yes --hwdec=vaapi --vo=gpu --profile=gpu-hq --prefetch-playlist=yes --video-latency-hacks=yes --osd-font='Fira Sans' --osd-font-size=23 --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5 --script=playlistmanager --script-opts=playlistmanager-loadfiles_on_start=yes"
alias mpvnv="mpv --loop-playlist=yes --hwdec=nvdec --vo=gpu --profile=gpu-hq --prefetch-playlist=yes --video-latency-hacks=yes --osd-font='Fira Sans' --osd-font-size=23 --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5 --script=playlistmanager --script-opts=playlistmanager-loadfiles_on_start=yes"
alias mpvcud="mpv --loop-playlist=yes --hwdec=cuda --vo=gpu --profile=gpu-hq --prefetch-playlist=yes --video-latency-hacks=yes --osd-font='Fira Sans' --osd-font-size=23 --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5 --script=playlistmanager --script-opts=playlistmanager-loadfiles_on_start=yes"
alias mpv="mpv --hwdec=auto --vo=gpu --sub-font='MotoyaLCedar' --sub-font-size=32 --sub-blur=3.5"

playlistmanagerスクリプトを使っている。 単独のmpvコマンドだけが単一ファイル用。