Codec (Linux): adds va-x11 method

This commit is contained in:
李通洲
2026-06-23 15:33:58 +08:00
parent 31c1431ac6
commit eff0108bb5
3 changed files with 190 additions and 125 deletions
+7 -2
View File
@@ -81,7 +81,8 @@ cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeB
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VA "Enable libva" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VADRM "Enable libva-drm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VAX11 "Enable libva-x11" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_VDPAU "Enable vdpau" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
@@ -1682,10 +1683,14 @@ ff_lib_enable(DRM
"libdrm"
"Libdrm"
)
ff_lib_enable(VA
ff_lib_enable(VADRM
"libva-drm"
"Libva-drm"
)
ff_lib_enable(VAX11
"libva-x11"
"Libva-x11"
)
ff_lib_enable(VDPAU
"vdpau"
"vdpau"
+5 -2
View File
@@ -268,8 +268,11 @@ void ffListFeatures(void) {
#if FF_HAVE_LIBZFS
"libzfs\n"
#endif
#if FF_HAVE_VA
"va\n"
#if FF_HAVE_VADRM
"va-drm\n"
#endif
#if FF_HAVE_VAX11
"va-x11\n"
#endif
#if FF_HAVE_VDPAU
"vdpau\n"
+178 -121
View File
@@ -1,5 +1,9 @@
#include "codec.h"
#if FF_HAVE_VADRM || FF_HAVE_VAX11
#define FF_HAVE_VA 1
#endif
#if FF_HAVE_VA || FF_HAVE_VDPAU
#include "common/library.h"
@@ -8,26 +12,22 @@
#include "common/io.h"
#if FF_HAVE_VA
#include <fcntl.h>
#include <va/va.h>
#include <va/va_drm.h>
#endif
#include <string.h>
typedef struct FFVAData {
FF_LIBRARY_SYMBOL(vaInitialize)
FF_LIBRARY_SYMBOL(vaTerminate)
FF_LIBRARY_SYMBOL(vaMaxNumProfiles)
FF_LIBRARY_SYMBOL(vaMaxNumEntrypoints)
FF_LIBRARY_SYMBOL(vaQueryConfigProfiles)
FF_LIBRARY_SYMBOL(vaQueryConfigEntrypoints)
FF_LIBRARY_SYMBOL(vaQueryVendorString)
FF_LIBRARY_SYMBOL(vaGetConfigAttributes)
} FFVAData;
#if FF_HAVE_VDPAU
#include <stdlib.h>
#include <vdpau/vdpau.h>
VdpStatus vdp_device_create_x11(void* display, int screen, VdpDevice* device, VdpGetProcAddress** get_proc_address);
void* XOpenDisplay(const char* display_name);
int XCloseDisplay(void* display);
int XDefaultScreen(void* display);
#endif
#if FF_HAVE_VA
static FFCodecType ffCodecProfileToType(VAProfile profile) {
static FFCodecType vaProfileToType(VAProfile profile) {
switch (profile) {
case 11: // VAProfileH263Baseline
return FF_CODEC_TYPE_H263;
@@ -96,7 +96,7 @@ static FFCodecType ffCodecProfileToType(VAProfile profile) {
}
}
static FFCodecShowType ffCodecGetEntrypointType(VAEntrypoint entrypoint) {
static FFCodecShowType vaGetEntrypointType(VAEntrypoint entrypoint) {
switch (entrypoint) {
case VAEntrypointVLD:
case VAEntrypointIDCT:
@@ -111,21 +111,20 @@ static FFCodecShowType ffCodecGetEntrypointType(VAEntrypoint entrypoint) {
}
}
static bool ffCodecProfileHasOutput(
static bool vaProfileHasOutput(
FFVAData* vaData,
VADisplay display,
__typeof__(vaQueryConfigEntrypoints)* ffvaQueryConfigEntrypoints,
__typeof__(vaGetConfigAttributes)* ffvaGetConfigAttributes,
int maxEntrypoints,
VAEntrypoint* entrypoints,
VAProfile profile,
FFCodecShowType entrypointType) {
int numEntrypoints = maxEntrypoints;
if (ffvaQueryConfigEntrypoints(display, profile, entrypoints, &numEntrypoints) != VA_STATUS_SUCCESS) {
if (vaData->ffvaQueryConfigEntrypoints(display, profile, entrypoints, &numEntrypoints) != VA_STATUS_SUCCESS) {
return false;
}
for (int i = 0; i < numEntrypoints; ++i) {
if (ffCodecGetEntrypointType(entrypoints[i]) != entrypointType) {
if (vaGetEntrypointType(entrypoints[i]) != entrypointType) {
continue;
}
@@ -134,7 +133,7 @@ static bool ffCodecProfileHasOutput(
.value = 0,
};
if (ffvaGetConfigAttributes(display, profile, entrypoints[i], &attrib, 1) == VA_STATUS_SUCCESS &&
if (vaData->ffvaGetConfigAttributes(display, profile, entrypoints[i], &attrib, 1) == VA_STATUS_SUCCESS &&
attrib.value != VA_ATTRIB_NOT_SUPPORTED &&
attrib.value != 0) {
return true;
@@ -144,17 +143,83 @@ static bool ffCodecProfileHasOutput(
return false;
}
static const char* ffDetectCodecByVa(FFCodecOptions* options, FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(libva, "libva" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaInitialize)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaTerminate)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaMaxNumProfiles)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaMaxNumEntrypoints)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaQueryConfigProfiles)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaQueryConfigEntrypoints)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaQueryVendorString)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libva, vaGetConfigAttributes)
static bool vaDetectDisplay(VADisplay display, FFVAData* vaData, FFCodecOptions* options, FFlist* result, const char* api) {
int major = 0, minor = 0;
if (vaData->ffvaInitialize(display, &major, &minor) != VA_STATUS_SUCCESS) {
vaData->ffvaTerminate(display);
return false;
}
int maxProfiles = vaData->ffvaMaxNumProfiles(display);
int maxEntrypoints = vaData->ffvaMaxNumEntrypoints(display);
if (maxProfiles <= 0 || maxEntrypoints <= 0) {
vaData->ffvaTerminate(display);
return false;
}
FF_AUTO_FREE VAProfile* profiles = (VAProfile*) malloc(sizeof(VAProfile) * (size_t) maxProfiles);
FF_AUTO_FREE VAEntrypoint* entrypoints = (VAEntrypoint*) malloc(sizeof(VAEntrypoint) * (size_t) maxEntrypoints);
int numProfiles = maxProfiles;
if (vaData->ffvaQueryConfigProfiles(display, profiles, &numProfiles) != VA_STATUS_SUCCESS) {
vaData->ffvaTerminate(display);
return false;
}
FFCodecType decoderTypes = FF_CODEC_TYPE_NONE;
FFCodecType encoderTypes = FF_CODEC_TYPE_NONE;
for (int j = 0; j < numProfiles; ++j) {
FFCodecType type = vaProfileToType(profiles[j]);
bool hasDecoder = (options->showType & FF_CODEC_SHOW_TYPE_DECODER) &&
!(decoderTypes & type) &&
vaProfileHasOutput(
vaData,
display,
maxEntrypoints,
entrypoints,
profiles[j],
FF_CODEC_SHOW_TYPE_DECODER);
bool hasEncoder = (options->showType & FF_CODEC_SHOW_TYPE_ENCODER) &&
!(encoderTypes & type) &&
vaProfileHasOutput(
vaData,
display,
maxEntrypoints,
entrypoints,
profiles[j],
FF_CODEC_SHOW_TYPE_ENCODER);
if (!hasDecoder && !hasEncoder) {
continue;
}
if (hasDecoder) {
decoderTypes |= type;
}
if (hasEncoder) {
encoderTypes |= type;
}
}
if (decoderTypes != FF_CODEC_TYPE_NONE || encoderTypes != FF_CODEC_TYPE_NONE) {
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
ffStrbufInitS(&item->gpu, vaData->ffvaQueryVendorString(display));
item->decoders = decoderTypes;
item->encoders = encoderTypes;
item->platformApi = api;
}
vaData->ffvaTerminate(display);
return true;
}
#if FF_HAVE_VADRM
#include <va/va_drm.h>
static const char* detectCodecByVaDrm(FFVAData* vaData, FFCodecOptions* options, FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(libvaDrm, "libva-drm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvaDrm, vaGetDisplayDRM)
@@ -182,84 +247,74 @@ static const char* ffDetectCodecByVa(FFCodecOptions* options, FFlist* result) {
continue;
}
int major = 0, minor = 0;
if (ffvaInitialize(display, &major, &minor) != VA_STATUS_SUCCESS) {
ffvaTerminate(display);
continue;
if (vaDetectDisplay(display, vaData, options, result, "VA-API (DRM)")) {
error = NULL;
}
error = NULL;
int maxProfiles = ffvaMaxNumProfiles(display);
int maxEntrypoints = ffvaMaxNumEntrypoints(display);
if (maxProfiles <= 0 || maxEntrypoints <= 0) {
ffvaTerminate(display);
continue;
}
FF_AUTO_FREE VAProfile* profiles = (VAProfile*) malloc(sizeof(VAProfile) * (size_t) maxProfiles);
FF_AUTO_FREE VAEntrypoint* entrypoints = (VAEntrypoint*) malloc(sizeof(VAEntrypoint) * (size_t) maxEntrypoints);
int numProfiles = maxProfiles;
if (ffvaQueryConfigProfiles(display, profiles, &numProfiles) != VA_STATUS_SUCCESS) {
ffvaTerminate(display);
continue;
}
FFCodecType decoderTypes = FF_CODEC_TYPE_NONE;
FFCodecType encoderTypes = FF_CODEC_TYPE_NONE;
for (int j = 0; j < numProfiles; ++j) {
FFCodecType type = ffCodecProfileToType(profiles[j]);
bool hasDecoder = (options->showType & FF_CODEC_SHOW_TYPE_DECODER) &&
!(decoderTypes & type) &&
ffCodecProfileHasOutput(
display,
ffvaQueryConfigEntrypoints,
ffvaGetConfigAttributes,
maxEntrypoints,
entrypoints,
profiles[j],
FF_CODEC_SHOW_TYPE_DECODER);
bool hasEncoder = (options->showType & FF_CODEC_SHOW_TYPE_ENCODER) &&
!(encoderTypes & type) &&
ffCodecProfileHasOutput(
display,
ffvaQueryConfigEntrypoints,
ffvaGetConfigAttributes,
maxEntrypoints,
entrypoints,
profiles[j],
FF_CODEC_SHOW_TYPE_ENCODER);
if (!hasDecoder && !hasEncoder) {
continue;
}
if (hasDecoder) {
decoderTypes |= type;
}
if (hasEncoder) {
encoderTypes |= type;
}
}
if (decoderTypes != FF_CODEC_TYPE_NONE || encoderTypes != FF_CODEC_TYPE_NONE) {
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
ffStrbufInitS(&item->gpu, ffvaQueryVendorString(display));
item->decoders = decoderTypes;
item->encoders = encoderTypes;
item->platformApi = "VA-API";
}
ffvaTerminate(display);
}
return error;
}
#endif
#if FF_HAVE_VAX11
#include <va/va_x11.h>
static const char* detectCodecByVaX11(FFVAData* vaData, FFCodecOptions* options, FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(libX11, "libX11" FF_LIBRARY_EXTENSION, 6)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XOpenDisplay)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XCloseDisplay)
Display* x11Display = ffXOpenDisplay(NULL);
if (!x11Display) {
return "XOpenDisplay() failed";
}
FF_LIBRARY_LOAD_MESSAGE(libvaX11, "libva-x11" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvaX11, vaGetDisplay)
VADisplay display = ffvaGetDisplay(x11Display);
if (!display) {
return "vaGetDisplay() failed";
}
if (!vaDetectDisplay(display, vaData, options, result, "VA-API (X11)")) {
return "VA-API could not detect any supported codec via X11";
}
return NULL;
}
#endif
static const char* detectCodecByVa(FFCodecOptions* options, FFlist* result) {
FFVAData vaData = {};
FF_LIBRARY_LOAD_MESSAGE(libva, "libva" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaInitialize)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaTerminate)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaMaxNumProfiles)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaMaxNumEntrypoints)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryConfigProfiles)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryConfigEntrypoints)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaQueryVendorString)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libva, vaData, vaGetConfigAttributes)
#if FF_HAVE_VADRM
if (detectCodecByVaDrm(&vaData, options, result) == NULL) {
return NULL;
}
#endif
#if FF_HAVE_VAX11
if (detectCodecByVaX11(&vaData, options, result) == NULL) {
return NULL;
}
#endif
return "VA-API could not detect any supported codec via DRM or X11";
}
#endif
#if FF_HAVE_VDPAU
#include <vdpau/vdpau_x11.h>
static const struct FFCodecVdpauCodec {
VdpDecoderProfile profile;
@@ -268,6 +323,13 @@ static const struct FFCodecVdpauCodec {
{ 0, FF_CODEC_TYPE_MPEG1 }, // VDP_DECODER_PROFILE_MPEG1
{ 1, FF_CODEC_TYPE_MPEG2 }, // VDP_DECODER_PROFILE_MPEG2_SIMPLE
{ 2, FF_CODEC_TYPE_MPEG2 }, // VDP_DECODER_PROFILE_MPEG2_MAIN
{ 6, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_BASELINE
{ 7, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_MAIN
{ 8, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH
{ 9, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_SIMPLE
{ 10, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_MAIN
{ 11, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_ADVANCED
{ 12, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_MPEG4_PART2_SP
{ 13, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_MPEG4_PART2_ASP
{ 14, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX4_QMOBILE
@@ -278,17 +340,16 @@ static const struct FFCodecVdpauCodec {
{ 19, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_MOBILE
{ 20, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_HOME_THEATER
{ 21, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_HD_1080P
{ 6, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_BASELINE
{ 7, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_MAIN
{ 8, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH
{ 22, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE
{ 23, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_EXTENDED
{ 24, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_PROGRESSIVE_HIGH
{ 25, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_CONSTRAINED_HIGH
{ 26, FF_CODEC_TYPE_H264 }, // VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE
{ 9, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_SIMPLE
{ 10, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_MAIN
{ 11, FF_CODEC_TYPE_VC1 }, // VDP_DECODER_PROFILE_VC1_ADVANCED
{ 27, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_0
{ 28, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_1
{ 29, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_2
{ 30, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_3
{ 100, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN
{ 101, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_10
{ 102, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_STILL
@@ -296,16 +357,12 @@ static const struct FFCodecVdpauCodec {
{ 104, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444
{ 105, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444_10
{ 106, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_444_12
{ 27, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_0
{ 28, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_1
{ 29, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_2
{ 30, FF_CODEC_TYPE_VP9 }, // VDP_DECODER_PROFILE_VP9_PROFILE_3
{ 107, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_MAIN
{ 108, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_HIGH
{ 109, FF_CODEC_TYPE_AV1 }, // VDP_DECODER_PROFILE_AV1_PROFESSIONAL
};
static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result) {
static const char* detectCodecByVdpau(FFCodecOptions* options, FFlist* result) {
if (!(options->showType & FF_CODEC_SHOW_TYPE_DECODER)) {
return "VDPAU only supports decoding";
}
@@ -315,14 +372,14 @@ static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XCloseDisplay)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XDefaultScreen)
FF_LIBRARY_LOAD_MESSAGE(libvdpau, "libvdpau" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvdpau, vdp_device_create_x11)
void* x11Display = ffXOpenDisplay(NULL);
Display* x11Display = ffXOpenDisplay(NULL);
if (!x11Display) {
return "XOpenDisplay() failed";
}
FF_LIBRARY_LOAD_MESSAGE(libvdpau, "libvdpau" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libvdpau, vdp_device_create_x11)
VdpDevice device = VDP_INVALID_HANDLE;
VdpGetProcAddress* ffvdp_get_proc_address = NULL;
if (ffvdp_device_create_x11(x11Display, ffXDefaultScreen(x11Display), &device, &ffvdp_get_proc_address) != VDP_STATUS_OK ||
@@ -389,12 +446,12 @@ const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list
FF_SUPPRESS_IO();
#if FF_HAVE_VA
if (ffDetectCodecByVa(options, result) == NULL) {
if (detectCodecByVa(options, result) == NULL) {
return NULL;
}
#endif
#if FF_HAVE_VDPAU
if (ffDetectCodecByVdpau(options, result) == NULL) {
if (detectCodecByVdpau(options, result) == NULL) {
return NULL;
}
#endif
@@ -406,7 +463,7 @@ const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list
const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
FF_UNUSED(options, result);
return "Fastfetch was built without DRM / VA-API / VDPAU headers";
return "Fastfetch was built without VA-API / VDPAU headers";
}
#endif