Manual

Enable VA-API HEVC decode on Fedora with an AMD GPU

Make an AMD GPU decode HEVC (Main and Main 10) through VA-API on Fedora 44 by installing RPM Fusion's mesa-va-drivers-freeworld, after checking that the hardware decodes HEVC and Fedora's own driver doesn't offer it.

Tested on
Fedora 44 desktop (KDE Plasma 6.7, X11), AMD Radeon 780M iGPU (radeonsi, phoenix), kernel 7.2.10-200.fc44, Mesa 26.2.5-1.fc44, mesa-va-drivers-freeworld 26.2.5-1.fc44, libva 2.23.0-3.fc44 (VA-API 1.23), libdrm 2.4.134-1.fc44, ffmpeg 8.1.3-1.fc44 (RPM Fusion), mpv 0.41.0-5.fc44 (2026-10-25).
Not verified
decoding a real H.264 clip (the H.264 profiles appear in step 11, but no H.264 clip was decoded); Haruna, browsers or other players with the new driver; Intel or NVIDIA GPUs; other distributions; Vulkan video decode; Wayland; 32-bit (i686) VA-API programs, and RPM Fusion's i686 build of mesa-va-drivers-freeworld (not installed here); what dnf does when Fedora ships a newer Mesa before RPM Fusion rebuilds this package (only the version pin was observed); the rollback.
Needs
an AMD GPU on the amdgpu kernel driver with render node /dev/dri/renderD128; the RPM Fusion free repository; RPM Fusion's ffmpeg for the test clips; mpv for the player check; python3; sudo for the install. The two scripts attached to this page: amdgpu_video_caps.py and va_profiles.py.
Time
15 min.
Risk
low. One package is added and nothing is removed (step 7). While it is installed, every 64-bit VA-API program on the host that doesn't set LIBVA_DRIVERS_PATH gets RPM Fusion's driver, which lists no JPEG decode profile. That driver file is a link to libgallium, the Mesa library that Fedora's EGL and GLX libraries and GBM's DRI backend also link, and the x86_64 package that step 8 installs puts its own copy ahead of Fedora's on the 64-bit linker path, so Fedora's 64-bit builds of those resolve to RPM Fusion's copy too; the 32-bit (i686) builds on this box keep Fedora's (Notes). The package pins the Mesa version, so each new Mesa version needs a matching rebuild from RPM Fusion. Undo: remove the package (not exercised).

Before you start#

  • Package versions and vendors:
    $ rpm -q --qf '%{NAME}-%{VERSION}-%{RELEASE} %{VENDOR}\n' ffmpeg ffmpeg-libs mpv libva libdrm mesa-dri-drivers
    ffmpeg-8.1.3-1.fc44 RPM Fusion
    ffmpeg-libs-8.1.3-1.fc44 RPM Fusion
    mpv-0.41.0-5.fc44 Fedora Project
    libva-2.23.0-3.fc44 Fedora Project
    libva-2.23.0-3.fc44 Fedora Project
    libdrm-2.4.134-1.fc44 Fedora Project
    libdrm-2.4.134-1.fc44 Fedora Project
    mesa-dri-drivers-26.2.5-1.fc44 Fedora Project
    mesa-dri-drivers-26.2.5-1.fc44 Fedora Project
    
    Expected: ffmpeg and ffmpeg-libs from RPM Fusion. Two lines for one package are its x86_64 and i686 builds (the format string prints no arch). If ffmpeg is not installed and Fedora's ffmpeg-free is, sudo dnf swap ffmpeg-free ffmpeg --allowerasing replaces it (that is how this box got it, in July); why that matters for players is in Two libavcodecs behind one soname.
  • The RPM Fusion free repository is configured:
    $ rpm -q rpmfusion-free-release
    rpmfusion-free-release-44-3.noarch
    
    Expected: an rpmfusion-free-release package for your Fedora release. The freeworld driver comes from rpmfusion-free-updates (step 9).
  • ffmpeg can encode the test clips:
    $ rpm -q --requires ffmpeg-libs | grep -E 'libx265|libSvtAv1Enc'
    libSvtAv1Enc.so.3()(64bit)
    libx265.so.215()(64bit)
    
    Expected: both libraries. Step 4 encodes with libx265 and libsvtav1. Fedora's ffmpeg-free was not tried for this.
  • The render node belongs to the amdgpu kernel driver:
    $ readlink /sys/class/drm/renderD128/device/driver
    ../../../../bus/pci/drivers/amdgpu
    
    Expected: a path ending in amdgpu.
  • The render node exists and your user can open it:
    $ ls -l /dev/dri/renderD128
    crw-rw-rw-. 1 root render 226, 128 Oct 20 18:56 /dev/dri/renderD128
    
    Expected: a character device. Mode crw-rw-rw- here, so no group membership is needed. Every command below uses /dev/dri/renderD128, the only render node on this box. With two GPUs, find the AMD node and change the path in both scripts and in the ffmpeg commands; for mpv's vaapi-copy the mpv manual names --vaapi-device [UNVERIFIED: single-GPU box].
  • Placeholders: none.
  • Backups: none needed. The package adds its VA drivers and its own libgallium under /usr/lib64/dri-freeworld/, one file in /etc/ld.so.conf.d/, and license and metainfo files; its install scriptlet runs ldconfig, which rebuilds the linker cache. Fedora's Mesa packages stay installed (steps 7 and 10).

Steps#

  1. Save the two scripts in an empty directory and work there.

    mkdir -p ~/vaapi-test && cd ~/vaapi-test
    

    Download amdgpu_video_caps.py and va_profiles.py from this page, or copy them from here. The first asks the amdgpu kernel driver through libdrm, the second asks libva.

    amdgpu_video_caps.py:

    # What the amdgpu kernel driver says the video block can do (AMDGPU_INFO_VIDEO_CAPS).
    import ctypes, os
    from ctypes import POINTER, byref, c_uint32, c_void_p, sizeof
    
    class CodecInfo(ctypes.Structure):
        _fields_ = [(f, c_uint32) for f in
                    ("valid", "max_width", "max_height", "max_pixels_per_frame", "max_level", "pad")]
    
    class VideoCaps(ctypes.Structure):
        _fields_ = [("codec_info", CodecInfo * 8)]
    
    CODECS = ["MPEG2", "MPEG4", "VC1", "H264", "HEVC", "JPEG", "VP9", "AV1"]
    lib = ctypes.CDLL("libdrm_amdgpu.so.1")
    lib.amdgpu_device_initialize.argtypes = [ctypes.c_int, POINTER(c_uint32), POINTER(c_uint32), POINTER(c_void_p)]
    lib.amdgpu_query_video_caps_info.argtypes = [c_void_p, ctypes.c_uint, ctypes.c_uint, c_void_p]
    
    fd = os.open("/dev/dri/renderD128", os.O_RDWR)
    major, minor, dev = c_uint32(), c_uint32(), c_void_p()
    assert lib.amdgpu_device_initialize(fd, byref(major), byref(minor), byref(dev)) == 0
    
    for kind, cap_type in (("decode", 0), ("encode", 1)):
        caps = VideoCaps()
        assert lib.amdgpu_query_video_caps_info(dev, cap_type, sizeof(caps), byref(caps)) == 0
        print(f"{kind}:")
        for name, c in zip(CODECS, caps.codec_info):
            if c.valid:
                print(f"  {name:5} {c.max_width}x{c.max_height} level {c.max_level}")
    

    va_profiles.py:

    # What the VA-API driver that libva actually loads offers, per profile.
    import ctypes, os
    from ctypes import POINTER, byref, c_char_p, c_int, c_void_p
    
    va = ctypes.CDLL("libva.so.2")
    va_drm = ctypes.CDLL("libva-drm.so.2")
    va_drm.vaGetDisplayDRM.restype = c_void_p
    va_drm.vaGetDisplayDRM.argtypes = [c_int]
    va.vaInitialize.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int)]
    va.vaQueryVendorString.restype = c_char_p
    va.vaQueryVendorString.argtypes = [c_void_p]
    va.vaMaxNumProfiles.argtypes = [c_void_p]
    va.vaMaxNumEntrypoints.argtypes = [c_void_p]
    va.vaQueryConfigProfiles.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int)]
    va.vaQueryConfigEntrypoints.argtypes = [c_void_p, c_int, POINTER(c_int), POINTER(c_int)]
    va.vaProfileStr.restype = c_char_p
    va.vaProfileStr.argtypes = [c_int]
    va.vaEntrypointStr.restype = c_char_p
    va.vaEntrypointStr.argtypes = [c_int]
    
    dpy = va_drm.vaGetDisplayDRM(os.open("/dev/dri/renderD128", os.O_RDWR))
    major, minor = c_int(), c_int()
    assert va.vaInitialize(dpy, byref(major), byref(minor)) == 0
    print(va.vaQueryVendorString(dpy).decode())
    
    profiles, n = (c_int * va.vaMaxNumProfiles(dpy))(), c_int()
    va.vaQueryConfigProfiles(dpy, profiles, byref(n))
    for p in profiles[:n.value]:
        eps, m = (c_int * va.vaMaxNumEntrypoints(dpy))(), c_int()
        va.vaQueryConfigEntrypoints(dpy, p, eps, byref(m))
        names = [va.vaEntrypointStr(e).decode().removeprefix("VAEntrypoint") for e in eps[:m.value]]
        print(f"  {va.vaProfileStr(p).decode().removeprefix('VAProfile'):26} {' '.join(names)}")
    

    Neither writes anything. Both open /dev/dri/renderD128 and print what comes back, using libdrm_amdgpu.so.1 (package libdrm) and libva.so.2 plus libva-drm.so.2 (package libva) through Python's ctypes. vainfo from libva-utils is the usual tool for the second list. It is not installed on this box, so its output is not shown here.

  2. Ask the kernel which codecs the video block decodes.

    $ python3 amdgpu_video_caps.py
    decode:
      H264  4096x4096 level 52
      HEVC  8192x4352 level 186
      JPEG  16384x16384 level 0
      VP9   8192x4352 level 0
      AV1   8192x4352 level 0
    encode:
      H264  4096x4096 level 0
      HEVC  8192x4352 level 0
      AV1   8192x4352 level 0
    

    Expected: an HEVC line under decode:. This is the kernel's AMDGPU_INFO_VIDEO_CAPS answer, read with libdrm's amdgpu_query_video_caps_info(): the 780M decodes H.264 up to 4096x4096 and HEVC up to 8192x4352. The answer has no profile field, so it can't tell Main from Main 10; the driver's list in step 3 can. If there is no HEVC line under decode:, this manual doesn't apply to your GPU.

  3. List what Fedora's own VA driver offers.

    $ LIBVA_DRIVERS_PATH=/usr/lib64/dri python3 va_profiles.py
    libva info: VA-API version 1.23.0
    libva info: Trying to open /usr/lib64/dri/radeonsi_drv_video.so
    libva info: Found init function __vaDriverInit_1_23
    libva info: va_openDriver() returns 0
    Mesa Gallium driver 26.2.5 for AMD Radeon 780M Graphics (radeonsi, phoenix, ACO, DRM 3.64, 7.2.10-200.fc44.x86_64)
      JPEGBaseline               VLD
      VP9Profile0                VLD
      VP9Profile2                VLD
      AV1Profile0                VLD EncSlice
      None                       VideoProc
    

    Expected: no H264… line and no HEVC… line. Fedora's driver decodes JPEG, VP9 and AV1 (VLD) and encodes AV1 (EncSlice). The GPU has HEVC (step 2), the driver build doesn't offer it. Fedora's mesa.spec passes no -Dvideo-codecs, so Mesa's default all_free applies, which Mesa's build options describe as enabling the codecs that aren't patent-encumbered.

    LIBVA_DRIVERS_PATH replaces libva's driver search list (colon-separated). Fedora builds libva to search /usr/lib64/dri-nonfree, then /usr/lib64/dri-freeworld, then /usr/lib64/dri. On a box without freeworld, plain python3 va_profiles.py tries the first two and loads the same Fedora file. With the variable set to /usr/lib64/dri, the command lists Fedora's driver even after step 8, which is how this page's "before" transcripts were made (Field notes).

  4. Generate three 2-second test clips.

    ffmpeg -f lavfi -i testsrc2=size=1920x1080:rate=30 -t 2 -c:v libx265 -pix_fmt yuv420p10le main10.mkv
    ffmpeg -f lavfi -i testsrc2=size=1920x1080:rate=30 -t 2 -c:v libx265 -pix_fmt yuv420p main8.mkv
    ffmpeg -f lavfi -i testsrc2=size=1920x1080:rate=30 -t 2 -c:v libsvtav1 -pix_fmt yuv420p av1.mkv
    
    $ ls -l main10.mkv main8.mkv av1.mkv
    -rw-r--r--. 1 user user 1497381 Oct 25 16:24 av1.mkv
    -rw-r--r--. 1 user user 1215321 Oct 25 16:24 main10.mkv
    -rw-r--r--. 1 user user 1205903 Oct 25 16:24 main8.mkv
    

    Expected: three files of 1.2 to 1.5 MB here: HEVC Main 10, HEVC Main (8-bit), and AV1 as the control. libx265 and libsvtav1 are software encoders, so this step doesn't depend on the VA driver, and no sample downloads are needed. ffmpeg's decode log names each clip's codec and profile (the Stream #0:0: Video: line in step 5).

  5. Decode the Main 10 clip through VA-API with Fedora's driver.

    $ LIBVA_DRIVERS_PATH=/usr/lib64/dri ffmpeg -hide_banner -v verbose -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i main10.mkv -f null -
    […]
      Stream #0:0: Video: hevc (Main 10), 1 reference frame, yuv420p10le(tv, progressive, left), 1920x1080 [SAR 1:1 DAR 16:9], 30 fps, 30 tbr, 1k tbn
    […]
    [VAAPI @ 0x5604256d4140] libva: Trying to open /usr/lib64/dri/radeonsi_drv_video.so
    […]
    [VAAPI @ 0x5604256d4140] VAAPI driver: Mesa Gallium driver 26.2.5 for AMD Radeon 780M Graphics (radeonsi, phoenix, ACO, DRM 3.64, 7.2.10-200.fc44.x86_64).
    […]
    [hevc @ 0x5604257bec40] No support for codec hevc profile 2.
    [hevc @ 0x5604257bec40] Failed setup for format vaapi: hwaccel initialisation returned error.
    [graph -1 input from stream 0:0 @ 0x7fb718004e80] w:1920 h:1080 pixfmt:yuv420p10le tb:1/1000 fr:30/1 sar:1/1 csp:unknown range:tv alpha:unspecified
    […]
    [in#0/matroska,webm @ 0x5604256cc580]   Input stream #0:0 (video): 60 packets read (1211848 bytes); 60 frames decoded; 0 decode errors;
    […]
    Exiting with exit code 0
    

    Expected with Fedora's driver: No support for codec hevc profile 2., then Failed setup for format vaapi: hwaccel initialisation returned error. Profile 2 is libavcodec's number for HEVC Main 10, profile 1 is Main: main8.mkv fails the same way with profile 1 (Failure modes, row 2). ffmpeg then decodes all 60 frames in software. The filter graph gets pixfmt:yuv420p10le, a CPU pixel format.

    Gotchaffmpeg exits 0 on the software fallback

    A failed hwaccel setup doesn't fail the ffmpeg run. ffmpeg drops VA-API, decodes in software, and ends with 0 decode errors and Exiting with exit code 0, the same as the working run in step 12. An exit-code test passes on both. Look for the Failed setup line, and, with -hwaccel_output_format vaapi as here, for pixfmt:vaapi on the graph -1 input line.

  6. Decode the AV1 control clip with the same driver.

    $ LIBVA_DRIVERS_PATH=/usr/lib64/dri ffmpeg -hide_banner -v verbose -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i av1.mkv -f null -
    […]
    [VAAPI @ 0x555fc65982c0] libva: Trying to open /usr/lib64/dri/radeonsi_drv_video.so
    […]
    [graph -1 input from stream 0:0 @ 0x7f2d10004ec0] w:1920 h:1080 pixfmt:vaapi tb:1/1000 fr:30/1 sar:1/1 csp:unknown range:tv alpha:unspecified
    […]
    [in#0/matroska,webm @ 0x555fc6585580]   Input stream #0:0 (video): 60 packets read (1496364 bytes); 60 frames decoded; 0 decode errors;
    […]
    

    Expected: no Failed setup line, and pixfmt:vaapi: the frames come out of the GPU as VA surfaces. The render node, libva and Fedora's driver work. Only the codec list is short.

  7. Dry-run the install.

    sudo dnf install --assumeno mesa-va-drivers-freeworld
    

    Expected: one package to install, mesa-va-drivers-freeworld, and nothing to remove or downgrade. --assumeno answers no at the prompt, so nothing changes. On this box dnf's own log (/var/log/dnf5.log) names the run dnf install --assumeno mesa-va-drivers-freeworld. The terminal output, with the repository loading cut:

    […]
    Repositories loaded.
    Package                    Arch   Version         Repository                  Size
    Installing:
     mesa-va-drivers-freeworld x86_64 0:26.2.5-1.fc44 rpmfusion-free-updates  53.0 MiB
    
    Transaction Summary:
     Installing:         1 package
    
    Total size of inbound packages is 14 MiB. Need to download 14 MiB.
    After this operation, 53 MiB extra will be used (install 53 MiB, remove 0 B).
    Operation aborted by the user.
    
  8. Install it.

    sudo dnf install mesa-va-drivers-freeworld
    

    Expected: the one-package transaction from step 7, then Complete!. Here dnf's log names the install dnf install -y mesa-va-drivers-freeworld, so there was no confirmation prompt. The terminal output:

    […]
    Package                    Arch   Version         Repository                  Size
    Installing:
     mesa-va-drivers-freeworld x86_64 0:26.2.5-1.fc44 rpmfusion-free-updates  53.0 MiB
    […]
    Running transaction
    [1/3] Verify package files              100% |  21.0   B/s |   1.0   B |  00m00s
    [2/3] Prepare transaction               100% |   1.0   B/s |   1.0   B |  00m01s
    [3/3] Installing mesa-va-drivers-freewo 100% |  33.7 MiB/s |  53.0 MiB |  00m02s
    Complete!
    

    The package is RPM Fusion's build of the same Mesa version with -Dvideo-codecs=h264dec,h264enc,h265dec,h265enc,vc1dec,av1dec,av1enc,vp9dec, installed into /usr/lib64/dri-freeworld/, the directory libva tries before Fedora's.

  9. Check the installed package.

    $ rpm -qi mesa-va-drivers-freeworld | grep -E "^(Version|Release|Install Date|Size|Vendor)"
    Version     : 26.2.5
    Release     : 1.fc44
    Install Date: Sun 25 Oct 2026 04:01:19 PM EET
    Size        : 55577925
    Vendor      : RPM Fusion
    
    $ dnf repoquery --installed --qf "%{name} %{from_repo}\n" mesa-va-drivers-freeworld
    mesa-va-drivers-freeworld rpmfusion-free-updates
    

    Expected: vendor RPM Fusion, the same version as mesa-dri-drivers (26.2.5 in Before you start), and an RPM Fusion repo. Size is in bytes: 55577925 is the 53 MiB from step 7.

  10. Check that both drivers are on disk.

    $ rpm -qf /usr/lib64/dri/radeonsi_drv_video.so /usr/lib64/dri-freeworld/radeonsi_drv_video.so
    mesa-dri-drivers-26.2.5-1.fc44.x86_64
    mesa-va-drivers-freeworld-26.2.5-1.fc44.x86_64
    

    Expected: Fedora's file still belongs to mesa-dri-drivers, the new one to mesa-va-drivers-freeworld. Nothing of Fedora's was replaced. libva finds the freeworld file first.

  11. List the profiles libva loads now.

    $ python3 va_profiles.py
    libva info: VA-API version 1.23.0
    libva info: Trying to open /usr/lib64/dri-nonfree/radeonsi_drv_video.so
    libva info: Trying to open /usr/lib64/dri-freeworld/radeonsi_drv_video.so
    libva info: Found init function __vaDriverInit_1_23
    libva info: va_openDriver() returns 0
    Mesa Gallium driver 26.2.5 for AMD Radeon 780M Graphics (radeonsi, phoenix, ACO, DRM 3.64, 7.2.10-200.fc44.x86_64)
      H264ConstrainedBaseline    VLD EncSlice
      H264Main                   VLD EncSlice
      H264High                   VLD EncSlice
      HEVCMain                   VLD EncSlice
      HEVCMain10                 VLD EncSlice
      VP9Profile0                VLD
      VP9Profile2                VLD
      AV1Profile0                VLD EncSlice
      None                       VideoProc
    

    Expected: libva stops at /usr/lib64/dri-freeworld/, and the list now has H264ConstrainedBaseline, H264Main, H264High, HEVCMain and HEVCMain10, each with VLD (decode) and EncSlice (encode). JPEGBaseline is gone: the freeworld build lists no JPEG decode profile (Notes).

  12. Decode the HEVC clips again, without the variable.

    $ ffmpeg -hide_banner -v verbose -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i main10.mkv -f null -
    […]
    [VAAPI @ 0x55bc56360140] libva: Trying to open /usr/lib64/dri-nonfree/radeonsi_drv_video.so
    [VAAPI @ 0x55bc56360140] libva: Trying to open /usr/lib64/dri-freeworld/radeonsi_drv_video.so
    [VAAPI @ 0x55bc56360140] libva: Found init function __vaDriverInit_1_23
    [VAAPI @ 0x55bc56360140] libva: va_openDriver() returns 0
    [VAAPI @ 0x55bc56360140] Initialised VAAPI connection: version 1.23
    [VAAPI @ 0x55bc56360140] VAAPI driver: Mesa Gallium driver 26.2.5 for AMD Radeon 780M Graphics (radeonsi, phoenix, ACO, DRM 3.64, 7.2.10-200.fc44.x86_64).
    […]
    [graph -1 input from stream 0:0 @ 0x7f5fa4004ec0] w:1920 h:1080 pixfmt:vaapi tb:1/1000 fr:30/1 sar:1/1 csp:unknown range:tv alpha:unspecified
    […]
    [in#0/matroska,webm @ 0x55bc56358580]   Input stream #0:0 (video): 60 packets read (1211848 bytes); 60 frames decoded; 0 decode errors;
    […]
    Exiting with exit code 0
    

    Expected: libva opens the freeworld driver, there is no No support or Failed setup line, and the graph input is pixfmt:vaapi: the GPU decoded the 60 frames. The 8-bit clip:

    $ ffmpeg -hide_banner -v verbose -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i main8.mkv -f null -
    […]
    [graph -1 input from stream 0:0 @ 0x7f9718004ec0] w:1920 h:1080 pixfmt:vaapi tb:1/1000 fr:30/1 sar:1/1 csp:unknown range:tv alpha:unspecified
    […]
    [in#0/matroska,webm @ 0x56516b88e580]   Input stream #0:0 (video): 60 packets read (1202435 bytes); 60 frames decoded; 0 decode errors;
    […]
    

    Expected: pixfmt:vaapi again.

Verify#

  • A player decodes on the GPU. The headless check with mpv:

    $ mpv --hwdec=vaapi-copy --vo=null -v main10.mkv
    […]
    [vd] Looking at hwdec hevc-vaapi-copy...
    [vaapi] libva: VA-API version 1.23.0
    [vaapi] libva: Trying to open /usr/lib64/dri-nonfree/radeonsi_drv_video.so
    [vaapi] libva: Trying to open /usr/lib64/dri-freeworld/radeonsi_drv_video.so
    [vaapi] libva: Found init function __vaDriverInit_1_23
    [vaapi] libva: va_openDriver() returns 0
    [vaapi] Initialized VAAPI: version 1.23
    [vd] Trying hardware decoding via hevc-vaapi-copy.
    […]
    [vd] Pixel formats supported by decoder: vaapi vulkan vdpau cuda yuv420p10le
    [vd] Codec profile: Main 10 (0x2)
    [vd] Requesting pixfmt 'vaapi' from decoder.
    [vd] Using hardware decoding (vaapi-copy).
    […]
    

    Expected: Using hardware decoding (vaapi-copy). mpv prints that line at its default log level (mpv source); -v shows the steps before it. With Fedora's driver, the same command ends in Attempting next decoding method after failure of hevc-vaapi-copy. and Using software decoding. (Failure modes, row 5).

  • The same check with a real window. During the first pass (16:02) I ran this; mpv's first log line is its own argument list:

    mpv --no-config --hwdec=vaapi --vo=gpu --ao=null --frames=30 --geometry=320x180 -v main10.mkv
    
    [cplayer] Command line options: '--no-config' '--hwdec=vaapi' '--vo=gpu' '--ao=null' '--frames=30' '--geometry=320x180' '-v' 'main10.mkv'
    […]
    [vd] Looking at hwdec hevc-vaapi...
    [vo/gpu] Loading hwdec drivers for format: 'vaapi'
    [vo/gpu] Loading hwdec driver 'vaapi'
    [vo/gpu/vaapi] using libplacebo dmabuf interop
    [vo/gpu/vaapi] Trying to open a x11 VA display...
    [vo/gpu/vaapi/vaapi] libva: VA-API version 1.23.0
    [vo/gpu/vaapi/vaapi] libva: Trying to open /usr/lib64/dri-nonfree/radeonsi_drv_video.so
    [vo/gpu/vaapi/vaapi] libva: Trying to open /usr/lib64/dri-freeworld/radeonsi_drv_video.so
    [vo/gpu/vaapi/vaapi] libva: Found init function __vaDriverInit_1_23
    [vo/gpu/vaapi/vaapi] libva: va_openDriver() returns 0
    [vo/gpu/vaapi/vaapi] Initialized VAAPI: version 1.23
    [vo/gpu/vaapi] Going to probe surface formats (may log bogus errors)...
    [vo/gpu/vaapi] Done probing surface formats.
    [vd] Trying hardware decoding via hevc-vaapi.
    […]
    [vd] Pixel formats supported by decoder: vaapi vulkan vdpau cuda yuv420p10le
    [vd] Codec profile: Main 10 (0x2)
    [vd] Requesting pixfmt 'vaapi' from decoder.
    [vd] Using hardware decoding (vaapi).
    […]
    [cplayer] VO: [gpu] 1920x1080 vaapi[p010]
    [cplayer] VO: Description: Shader-based GPU Renderer
    […]
    

    Expected: Using hardware decoding (vaapi). The GPU video output opens the VA display itself (the [vo/gpu/vaapi] lines), and libva loads the freeworld driver. This run was not repeated for this page.

    Gotcha--hwdec=vaapi with --vo=null decodes in software even with a working driver

    mpv's direct vaapi mode takes its GPU device from the video output. Its manual lists --vo=gpu, --vo=gpu-next, --vo=vaapi and --vo=dmabuf-wayland for it, and the null output creates no device (mpv source). This run was made with freeworld installed. mpv never got as far as libva (no libva: lines) and fell back to software. Use --hwdec=vaapi-copy for headless checks.

    $ mpv --hwdec=vaapi --vo=null -v main10.mkv
    […]
    [vd] Opening decoder hevc
    [vd] Looking at hwdec hevc-vaapi...
    [vd] Could not create device.
    [vd] Using software decoding.
    […]
    

Undo / rollback#

  • Per command, without uninstalling: prefix it with LIBVA_DRIVERS_PATH=/usr/lib64/dri. Steps 3, 5 and 6 ran that way with freeworld installed and got Fedora's driver. Checked only with ffmpeg, mpv with --vo=null, va_profiles.py and a maps probe (Field notes), not with a program that also renders through OpenGL: Fedora's 64-bit EGL and GLX libraries and 64-bit GBM DRI backend now resolve to RPM Fusion's libgallium (Notes).
  • Remove the package:
    sudo dnf remove mesa-va-drivers-freeworld
    
    Read the transaction before you answer; it should list only that package. Afterwards python3 va_profiles.py should show Fedora's list from step 3 again, with JPEGBaseline and without H264… or HEVC… lines. [UNVERIFIED: rollback not exercised]
  • Delete the test directory (the two scripts and the three clips):
    rm -r ~/vaapi-test
    

Failure modes#

Symptom (exact message)CauseFix
ffmpeg: No support for codec hevc profile 2., then Failed setup for format vaapi: hwaccel initialisation returned error.libva loaded Fedora's radeonsi driver, which has no HEVC profiles (step 3)Steps 7 and 8. If freeworld is installed already, look for a LIBVA_DRIVERS_PATH in the environment (env | grep LIBVA)
ffmpeg on main8.mkv: No support for codec hevc profile 1., then the same Failed setup lineSame driver, 8-bit HEVC MainSame as row 1
ffmpeg: 60 frames decoded; 0 decode errors; and Exiting with exit code 0 after a Failed setup lineffmpeg drops a hwaccel that fails setup and decodes in software; libavcodec retries the format negotiation without itJudge by the Failed setup line and the pixfmt: on the graph -1 input line, not by the exit code (step 5)
mpv: [vd] Looking at hwdec hevc-vaapi..., [vd] Could not create device., [vd] Using software decoding.--hwdec=vaapi with --vo=null: the null output gives the direct vaapi mode no GPU device--hwdec=vaapi-copy for headless checks, or a real --vo (Verify)
mpv: [ffmpeg/video] hevc: No support for codec hevc profile 2. … [vd] Attempting next decoding method after failure of hevc-vaapi-copy., then [vd] Using software decoding.Fedora's driver; here forced with LIBVA_DRIVERS_PATH=/usr/lib64/driSteps 7 and 8

Field notes#

  • 2026-10-25, 16:24–17:29, same box and package versions as the entry below, plus mesa-va-drivers-freeworld 26.2.5-1.fc44: I re-captured the transcripts on this page, except the dnf output in steps 7 and 8 and the --vo=gpu run, which come from the first pass. I generated the clips again with the step 4 commands (file times 16:24), ran the "before" commands with LIBVA_DRIVERS_PATH=/usr/lib64/dri and the "after" commands without it. A small libva client that prints its own /proc/self/maps mapped Fedora's /usr/lib64/libgallium-26.2.5.so with the variable set and /usr/lib64/dri-freeworld/libgallium-26.2.5.so without it. The runs with LIBVA_DRIVERS_PATH set gave the same error lines and the same profile list as the first pass. New in this pass: the freeworld driver lists no JPEGBaseline, the package puts /usr/lib64/dri-freeworld/ on the linker path, and ldd resolves Fedora's 64-bit EGL and GLX libraries and 64-bit GBM DRI backend (/usr/lib64/gbm/dri_gbm.so) to RPM Fusion's libgallium, while their i686 builds keep Fedora's. The two scripts, run again at 16:41, printed output byte-identical to their 16:35 runs. The --vo=gpu check was not repeated.
  • 2026-10-25, 15:26–16:15, Fedora 44 desktop (KDE Plasma 6.7, X11), AMD Radeon 780M (phoenix); kernel 7.2.10-200.fc44, Mesa 26.2.5-1.fc44, libva 2.23.0-3.fc44, libdrm 2.4.134-1.fc44, ffmpeg 8.1.3-1.fc44 (RPM Fusion), mpv 0.41.0-5.fc44: The first pass, before freeworld. In July (Mesa 26.0.8 then) I had taken hwaccel initialisation returned error, and an mpv trace where hevc-vulkan called the stream unsupported, to mean the GPU couldn't decode HEVC Main 10. This time I checked the hardware, the driver and a real decode separately. vainfo (libva-utils) wasn't installed; two ctypes probes, earlier versions of the scripts on this page, asked the kernel and libva directly. The kernel listed HEVC decode up to 8192x4352. Fedora's driver, which libva found in /usr/lib64/dri after trying dri-nonfree and dri-freeworld, listed JPEG, VP9 and AV1 decode and no H.264 or HEVC at all, not even 8-bit Main. The generated Main 10 and Main clips failed with profile 2 and profile 1, the AV1 clip decoded through VA-API, and ffmpeg exited 0 after decoding all 60 frames each time. The dry run (dnf install --assumeno) planned one package, 53 MiB, no removals. I installed mesa-va-drivers-freeworld 26.2.5-1.fc44 from rpmfusion-free-updates with dnf install -y (rpm's install time: 16:01). The H.264 and HEVC profiles appeared, and both HEVC clips decoded with no Failed setup. My first mpv check after that, --hwdec=vaapi --vo=null -v, ended in Using software decoding. and looked as if the fix had failed. --hwdec=vaapi-copy --vo=null reported Using hardware decoding (vaapi-copy)., and with a real window (--vo=gpu) mpv reported Using hardware decoding (vaapi).

Notes#

  • Why Fedora's build lacks H.264 and HEVC: in September 2022 Fedora removed its explicit -Dvideo-codecs=h264dec,h264enc,h265dec,h265enc,vc1dec line from mesa.spec (commit "Drop codecs.": no legal approval, and the codecs had shipped by accident). Since then the build has relied on Mesa's default, which leaves them out (since Mesa 24.0 that default is named all_free). The story of how I first blamed the GPU is in the background post.
  • JPEG: the freeworld driver lists no JPEGBaseline, Fedora's does (steps 3 and 11). RPM Fusion's codec list has no jpegdec, which fits. A program that needs VA-API JPEG decode can be pointed at Fedora's driver with LIBVA_DRIVERS_PATH=/usr/lib64/dri (JPEG decode itself not tested).
  • Mesa updates: the package requires the installed Mesa version exactly (the version, not the release):
    $ rpm -q --requires mesa-va-drivers-freeworld | grep mesa-filesystem; rpm -q mesa-filesystem
    mesa-filesystem(x86-64) = 26.2.5
    mesa-filesystem-26.2.5-1.fc44.i686
    mesa-filesystem-26.2.5-1.fc44.x86_64
    
    So each new Mesa version from Fedora needs a matching freeworld build; a release-only update of 26.2.5 still fits the pin. The only reason the spec gives is a 2023 changelog line: the version is enforced to avoid a mismatch with Fedora. What dnf does when Fedora's Mesa update arrives before RPM Fusion's rebuild: not observed.
  • Linker path: the package adds /usr/lib64/dri-freeworld/ through /etc/ld.so.conf.d/mesa-freeworld-lib64.conf (written by its spec), and its install scriptlet runs ldconfig, so the dynamic linker now finds RPM Fusion's libgallium-26.2.5.so before Fedora's for Fedora's 64-bit EGL and GLX libraries and 64-bit GBM DRI backend too (libgbm.so.1 itself doesn't link libgallium):
    $ ldd /usr/lib64/libEGL_mesa.so.0 /usr/lib64/libGLX_mesa.so.0 /usr/lib64/gbm/dri_gbm.so | grep -E '^/|gallium'
    /usr/lib64/libEGL_mesa.so.0:
    	libgallium-26.2.5.so => /usr/lib64/dri-freeworld/libgallium-26.2.5.so (0x00007f5d68e00000)
    /usr/lib64/libGLX_mesa.so.0:
    	libgallium-26.2.5.so => /usr/lib64/dri-freeworld/libgallium-26.2.5.so (0x00007f1f31400000)
    /usr/lib64/gbm/dri_gbm.so:
    	libgallium-26.2.5.so => /usr/lib64/dri-freeworld/libgallium-26.2.5.so (0x00007fee06400000)
    
    Step 8 installed only the x86_64 build, and its file adds only the 64-bit directory. The i686 builds of the same libraries, installed on this box too, still resolve to Fedora's copy (/lib/libgallium-26.2.5.so, package mesa-dri-drivers.i686):
    $ ldd /usr/lib/libEGL_mesa.so.0 /usr/lib/libGLX_mesa.so.0 /usr/lib/gbm/dri_gbm.so | grep -E '^/|gallium'
    /usr/lib/libEGL_mesa.so.0:
    	libgallium-26.2.5.so => /lib/libgallium-26.2.5.so (0xf44cb000)
    /usr/lib/libGLX_mesa.so.0:
    	libgallium-26.2.5.so => /lib/libgallium-26.2.5.so (0xf4499000)
    /usr/lib/gbm/dri_gbm.so:
    	libgallium-26.2.5.so => /lib/libgallium-26.2.5.so (0xf456b000)
    
    RPM Fusion also ships an i686 build, mesa-va-drivers-freeworld.i686, in the same Fedora 44 x86_64 updates repo. Its file list has /etc/ld.so.conf.d/mesa-freeworld-lib.conf and its own /usr/lib/dri-freeworld/libgallium-26.2.5.so. It was not installed or tested here, so what it does to the 32-bit libraries was not observed. Nothing on the OpenGL side was tested beyond this.
  • No dnf swap is needed: on Fedora 44 mesa-va-drivers is not a package of its own (rpm -q mesa-va-drivers says not installed; mesa-dri-drivers provides the name), and the plain install removed nothing.
  • mpv log levels, from mpv's source: of the mpv decoder lines on this page, only Using hardware decoding (…) prints at the default level. Looking at hwdec …, Could not create device. and Using software decoding. need -v, and so does Attempting next decoding method … before the first frame (vd_lavc.c). libavcodec's own errors, such as No support for codec hevc profile 2., pass through at mpv's error level (common/av_log.c), above mpv's default terminal level (common/msg.c), so they print without -v. A fallback that never reaches libavcodec's hwaccel setup, as with --hwdec=vaapi --vo=null, prints no decoder line at the default level. [UNVERIFIED: read from the source; no mpv run without -v] Use -v when a missing line would be the answer.

Filed under: vaapi, fedora, amd, ffmpeg, linux

Sources#