Table of Contents

ffmpeg - Hardware transcoding using GPUs - AMD GPU

Basic method

ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i "input.mkv" -map 0:v -metadata:s:v:0 language=eng -map 0:a -metadata:s:a:0 language=eng -map 0:s? -metadata:s:s:0 language=eng -c:v hevc_vaapi -c:a copy -c:s copy -global_quality 28 "output.mkv"
 
 
ffmpeg -i "input.mkv" -vaapi_device /dev/dri/renderD128 -vcodec hevc_vaapi -vf format='nv12|vaapi,hwupload' -map 0 -c:a copy -c:s copy -qp 23 "output.mkv"

Step-by-step guide to the above mentioned method

Determine which codecs can be used with GPU hardware video encoding acceleration

vainfo

returns:

vainfo
libva info: VA-API version 1.16.0
libva info: User environment variable requested driver 'radeonsi'
libva info: Trying to open /opt/amdgpu/lib/x86_64-linux-gnu/dri/radeonsi_drv_video.so
libva info: Found init function __vaDriverInit_1_16
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.16 (libva 2.12.0)
vainfo: Driver version: Mesa Gallium driver 23.3.0-devel for Radeon RX 7900 XTX (navi31, LLVM 17.0.4, DRM 3.54, 6.5.0-15-generic)
vainfo: Supported profile and entrypoints
      VAProfileH264ConstrainedBaseline:	VAEntrypointVLD
      VAProfileH264ConstrainedBaseline:	VAEntrypointEncSlice
      VAProfileH264Main               :	VAEntrypointVLD
      VAProfileH264Main               :	VAEntrypointEncSlice
      VAProfileH264High               :	VAEntrypointVLD
      VAProfileH264High               :	VAEntrypointEncSlice
      VAProfileHEVCMain               :	VAEntrypointVLD
      VAProfileHEVCMain               :	VAEntrypointEncSlice
      VAProfileHEVCMain10             :	VAEntrypointVLD
      VAProfileHEVCMain10             :	VAEntrypointEncSlice
      VAProfileJPEGBaseline           :	VAEntrypointVLD
      VAProfileVP9Profile0            :	VAEntrypointVLD
      VAProfileVP9Profile2            :	VAEntrypointVLD
      VAProfileAV1Profile0            :	VAEntrypointVLD
      VAProfileAV1Profile0            :	VAEntrypointEncSlice
      VAProfileNone                   :	VAEntrypointVideoProc

NOTE: For all entries with a value of VAEntrypointEncSlice hardware encoding can be used.

In this case this shows the following as able to hardware encode:

      VAProfileH264ConstrainedBaseline:	VAEntrypointEncSlice
      VAProfileH264Main               :	VAEntrypointEncSlice
      VAProfileH264High               :	VAEntrypointEncSlice
      VAProfileHEVCMain               :	VAEntrypointEncSlice
      VAProfileHEVCMain10             :	VAEntrypointEncSlice
      VAProfileAV1Profile0            :	VAEntrypointEncSlice

Check what vaapi encoders are supported by ffmpeg

ffmpeg -encoders | grep vaapi

returns:

ffmpeg version N-113695-g32538dafca Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 11 (Ubuntu 11.4.0-1ubuntu1~22.04)
  configuration: --prefix=/home/peter/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/peter/ffmpeg_build/include --extra-ldflags=-L/home/peter/ffmpeg_build/lib --extra-libs='-lpthread -lm' --ld=g++ --bindir=/home/peter/bin --enable-gpl --enable-gnutls --enable-libaom --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libsvtav1 --enable-libdav1d --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree --extra-libs=-lpthread
  libavutil      58. 39.100 / 58. 39.100
  libavcodec     60. 39.101 / 60. 39.101
  libavformat    60. 21.100 / 60. 21.100
  libavdevice    60.  4.100 / 60.  4.100
  libavfilter     9. 17.100 /  9. 17.100
  libswscale      7.  6.100 /  7.  6.100
  libswresample   4. 13.100 /  4. 13.100
  libpostproc    57.  4.100 / 57.  4.100
 V....D av1_vaapi            AV1 (VAAPI) (codec av1)
 V....D h264_vaapi           H.264/AVC (VAAPI) (codec h264)
 V....D hevc_vaapi           H.265/HEVC (VAAPI) (codec hevc)
 V....D mjpeg_vaapi          MJPEG (VAAPI) (codec mjpeg)
 V....D mpeg2_vaapi          MPEG-2 (VAAPI) (codec mpeg2video)
 V....D vp8_vaapi            VP8 (VAAPI) (codec vp8)
 V....D vp9_vaapi            VP9 (VAAPI) (codec vp9)

NOTE: This confirms that ffmpeg supports the following vaapi codecs:

 V....D av1_vaapi            AV1 (VAAPI) (codec av1)
 V....D h264_vaapi           H.264/AVC (VAAPI) (codec h264)
 V....D hevc_vaapi           H.265/HEVC (VAAPI) (codec hevc)
 V....D mjpeg_vaapi          MJPEG (VAAPI) (codec mjpeg)
 V....D mpeg2_vaapi          MPEG-2 (VAAPI) (codec mpeg2video)
 V....D vp8_vaapi            VP8 (VAAPI) (codec vp8)
 V....D vp9_vaapi            VP9 (VAAPI) (codec vp9)


ffmpeg -i "input.mkv" -vaapi_device /dev/dri/renderD128 -vcodec hevc_vaapi -vf format='nv12|vaapi,hwupload' -map 0 -c:a copy -c:s copy -qp 23 "output.mkv"

NOTE:

  • -vaapi_device /dev/dri/renderD128, which is a shortcut to -init_hw_device vaapi=vaapi0:/dev/dri/renderD128 -filter_hw_device vaapi0, initializes a new hardware device of type vaapi.
  • -vcodec hevc_vaapi
  • -vf 'format=nv12,hwupload' creates the filtergraph and uses it to filter the stream.
    • The encoders only accept input as VAAPI surfaces.
    • If the input is in normal memory, it will need to be uploaded before giving the frames to the encoder; in the ffmpeg utility, the hwupload filter can be used for this.
    • It will upload to a surface with the same layout as the software frame, so it may be necessary to add a format filter immediately before to get the input into the right format (hardware generally wants the nv12 layout).
    • The hwupload filter also requires a device to upload to, which needs to be defined before the filter graph is created, which is done with -vaapi_device.
  • -map 0 -c:a copy -c:s copy: This causes to copy the audio streams and sub without modification to the new file.
  • -map 0:a -c:a copy: This causes to copy the audio streams without modification to the new file.
  • -qp 23: The video quality.
    • The lower the value, the better will be the video quality, but also the files will be larger.
    • The default value is 25 which is fairly good.
    • For high-definition videos a value between 21-23 works best and produces good results.


AMD GPUs

h264_amf
hevc_amf

Decoding

-hwaccel d3d11va

Encoding

For video resolution <= 4K

-c:v libx264
 
or
 
-c:v h264_amf

For video resolution > 4K

-c:v libx265 
 
or
 
-c:v hevc_amf

Examples

#1 - A corrupt 1920×1080 video:

ffmpeg -y -vsync 0 -i "input.mp4" -c:a copy -c:v h264_amf -pix_fmt yuv420p "output.mp4"

#2 - a 7680×3840 H.265 video with incompatible profile for VHT - a stutter playback 7260×3630 60fps 10bit video

ffmpeg -y -vsync 0 -i "input.mp4" -c:a copy -c:v hevc_amf -pix_fmt yuv420p "output.mp4"

#3 - a 7680×7680 video not hardware decoded because is H.264 encoded

ffmpeg -y -vsync 0 -i "input.mp4" -c:a copy -c:v hevc_amf -pix_fmt yuv420p "output.mp4" 

References