理屈としては解説してきたものの、実際にVA-APIでVCEを叩いたことがなかったのでやってみた。 ついでなので、qsvやnvenc、あるいはlibx264などでも応用できるウェブカメラとスクリーンキャスティングの話もしておく。

基本的な手順は単純で、AMDGPU(事実上現在唯一となったAMDビデオドライバ)を選択した上で、 VA-APIを有効にし、VA-API経由でエンコーディングを行う。

注意点としては古くなったプロプライエタリドライバ(Catalyst)ではなく、AMDGPUドライバーを使用することと、 MESA VAドライバを使用することである。

RadeonはVA-API/VDPAUの両方をサポートしており、NvidiaのようにVDPAUドライバをインストールし、VA VDPAUアダプタを使用するという方法(libva-dvpau-driver)も成立してしまう。 しかし、この場合は動作しなくなるので、必ずMESA VAドライバ(libva-mesa-driver)を使用する必要がある。

その上で基本はこんな感じ。 (Arch/ManjaroのffmpegはVA-APIを含んでいるのでffmpeg云々の話はない)

$ ffmpeg -vaapi_device /dev/dri/renderD128 -i source.avi -vf 'format=nv12,hwupload' -c:v h264_vaapi -qp 24 -c:a copy outfile.mp4

ffmpeg上でのVA-APIは公式にドキュメントがある

ソースファイルがビデオアクセラレーションが効くのであればUVDをVA-API経由で叩いてデコードすることもできる。

$ ffmpeg -vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi -i source.avi -vf 'format=nv12,hwupload' -c:v h264_vaapi -qp 24 -c:a copy outfile.mp4

ところがこれではうまくいかなかった。 一件成功しているように見えるのだが、フレームの全くないビデオファイルが出来上がってしまい再生できない。

多分、新しいRadeonだとそんなことはないのだろうと思うけれども、Godavari(2015年)のR7グラフィックスでは問題があったため、-profile 578を指定すると解決した。

$ ffmpeg -vaapi_device /dev/dri/renderD128 -i source.avi -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -bf 0 -qp 24 -c:a copy outfile.mp4

ウェブカムからキャプチャする場合はエンコードのみ、入力はv4l2:

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f v4l2 -i /dev/video0 -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -qp 24 outfile.mp4

さらにマイクをPulseAudio経由で拾う場合。音声は192k AAC:

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f v4l2 -i /dev/video0 -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

X11のスクリーンキャスティング 音声つき。 A10-7870Kだとh264_vaapiは34fpsくらいなので、60fpsはフレーム落ちばかりになる。30fpsも無理で24fpsがドロップしない限界。 ultrafastにした場合は30fpsは可能だけれど60fpsは無理。

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -framerate 24 -video_size 1920x1080 -i $DISPLAY -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

ultrafastで30fps:

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -framerate 30 -video_size 1920x1080 -i $DISPLAY -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -preset ultrafast -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

なお、-video_size-iよりも先に指定することが必須である。基本的にffmpegはオプションは順番に厳しい。

300×300のウィンドウを左上から200×200のオフセットで録画する場合

$ ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -framerate 30 -video_size 300x300 -i $DISPLAY+200,200 -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -preset ultrafast -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

-video_sizeの指定方法は色々あって、公式ドキュメントで解説されている。 なので、-video_size 1920x1080ならば-video_size hd1080とも書ける。

録画領域を表示するには-show_region 1

$ ffmpeg -show_region 1 -vaapi_device /dev/dri/renderD128 -f x11grab -framerate 30 -video_size hd1080 -i $DISPLAY -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile 578 -preset ultrafast -qp 24 -f alsa -i pulse -c:a aac -b:a 192k outfile.mp4

NVENCだとmkvにもできるので音声はFLACやOpusで撮ることもできるのだけど、AMDGPU VA-APIはmp4だけ

使ってみた感想としては、QSVと違ってCPUがあくのは良いけれど、R7の速度自体がCPUと大差ない(libx264でやったのと同程度)であるため、ちょっと微妙かもしれない。 A10でもスクリーンキャスティングしながら配信みたいなことができるというメリットはあるけれども。

コメントを残す

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

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください