From 35428606e72d86a68e1e1ffcbf6977aca404cc65 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 1 Jun 2026 18:02:15 +0800 Subject: [PATCH] Codec (Linux): adds FFCodecShowOptions; code cleanup --- doc/json_schema.json | 19 +++ src/detection/codec/codec_linux.c | 204 ++++++++++-------------------- src/modules/codec/codec.c | 31 +++++ src/modules/codec/option.h | 9 ++ 4 files changed, 126 insertions(+), 137 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 505d27633..f97d53ae4 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1914,6 +1914,25 @@ "type": "boolean", "default": false }, + "showType": { + "description": "Which types of codecs to detect and show", + "type": "string", + "oneOf": [ + { + "const": "both", + "description": "Show both decoders and encoders" + }, + { + "const": "decoder", + "description": "Show only decoders" + }, + { + "const": "encoder", + "description": "Show only encoders" + } + ], + "default": "both" + }, "key": { "$ref": "#/$defs/key" }, diff --git a/src/detection/codec/codec_linux.c b/src/detection/codec/codec_linux.c index 2a38b6353..d22dc9024 100644 --- a/src/detection/codec/codec_linux.c +++ b/src/detection/codec/codec_linux.c @@ -203,7 +203,7 @@ static void ffCodecFillGpuName(const drmDevice* dev, const char* path, FFstrbuf* } } -static const char* ffDetectCodecByVa(FFlist* result, bool* initialized) { +static const char* ffDetectCodecByVa(FFCodecOptions* options, FFlist* result, bool* initialized) { *initialized = false; FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2) @@ -288,23 +288,25 @@ static const char* ffDetectCodecByVa(FFlist* result, bool* initialized) { FFCodecType decoderTypes = FF_CODEC_TYPE_NONE; FFCodecType encoderTypes = FF_CODEC_TYPE_NONE; for (int j = 0; j < numProfiles; ++j) { - bool hasDecoder = ffCodecProfileHasOutput( - display, - ffvaQueryConfigEntrypoints, - ffvaGetConfigAttributes, - maxEntrypoints, - entrypoints, - profiles[j], - false); + bool hasDecoder = (options->showType & FF_CODEC_SHOW_TYPE_DECODER) && + ffCodecProfileHasOutput( + display, + ffvaQueryConfigEntrypoints, + ffvaGetConfigAttributes, + maxEntrypoints, + entrypoints, + profiles[j], + false); - bool hasEncoder = ffCodecProfileHasOutput( - display, - ffvaQueryConfigEntrypoints, - ffvaGetConfigAttributes, - maxEntrypoints, - entrypoints, - profiles[j], - true); + bool hasEncoder = (options->showType & FF_CODEC_SHOW_TYPE_ENCODER) && + ffCodecProfileHasOutput( + display, + ffvaQueryConfigEntrypoints, + ffvaGetConfigAttributes, + maxEntrypoints, + entrypoints, + profiles[j], + true); if (!hasDecoder && !hasEncoder) { continue; @@ -312,10 +314,10 @@ static const char* ffDetectCodecByVa(FFlist* result, bool* initialized) { FFCodecType type = ffCodecProfileToType(profiles[j]); if (hasDecoder) { - decoderTypes = (FFCodecType) ((uint32_t) decoderTypes | (uint32_t) type); + decoderTypes |= type; } if (hasEncoder) { - encoderTypes = (FFCodecType) ((uint32_t) encoderTypes | (uint32_t) type); + encoderTypes |= type; } } @@ -341,123 +343,51 @@ static const struct FFCodecVdpauCodec { VdpDecoderProfile profile; FFCodecType type; } FF_CODEC_VDPAU_CODECS[] = { - #ifdef VDP_DECODER_PROFILE_MPEG1 - { VDP_DECODER_PROFILE_MPEG1, FF_CODEC_TYPE_MPEG1 }, - #endif - #ifdef VDP_DECODER_PROFILE_MPEG2_SIMPLE - { VDP_DECODER_PROFILE_MPEG2_SIMPLE, FF_CODEC_TYPE_MPEG2 }, - #endif - #ifdef VDP_DECODER_PROFILE_MPEG2_MAIN - { VDP_DECODER_PROFILE_MPEG2_MAIN, FF_CODEC_TYPE_MPEG2 }, - #endif - #ifdef VDP_DECODER_PROFILE_MPEG4_PART2_SP - { VDP_DECODER_PROFILE_MPEG4_PART2_SP, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_MPEG4_PART2_ASP - { VDP_DECODER_PROFILE_MPEG4_PART2_ASP, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_DIVX4_QMOBILE - { VDP_DECODER_PROFILE_DIVX4_QMOBILE, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_DIVX4_MOBILE - { VDP_DECODER_PROFILE_DIVX4_MOBILE, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_DIVX4_HOME_THEATER - { VDP_DECODER_PROFILE_DIVX4_HOME_THEATER, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_DIVX4_HD_1080P - { VDP_DECODER_PROFILE_DIVX4_HD_1080P, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_DIVX5_QMOBILE - { VDP_DECODER_PROFILE_DIVX5_QMOBILE, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_DIVX5_MOBILE - { VDP_DECODER_PROFILE_DIVX5_MOBILE, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_DIVX5_HOME_THEATER - { VDP_DECODER_PROFILE_DIVX5_HOME_THEATER, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_DIVX5_HD_1080P - { VDP_DECODER_PROFILE_DIVX5_HD_1080P, FF_CODEC_TYPE_DIVX_XVID }, - #endif - #ifdef VDP_DECODER_PROFILE_H264_BASELINE - { VDP_DECODER_PROFILE_H264_BASELINE, FF_CODEC_TYPE_H264 }, - #endif - #ifdef VDP_DECODER_PROFILE_H264_MAIN - { VDP_DECODER_PROFILE_H264_MAIN, FF_CODEC_TYPE_H264 }, - #endif - #ifdef VDP_DECODER_PROFILE_H264_HIGH - { VDP_DECODER_PROFILE_H264_HIGH, FF_CODEC_TYPE_H264 }, - #endif - #ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE - { VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE, FF_CODEC_TYPE_H264 }, - #endif - #ifdef VDP_DECODER_PROFILE_H264_EXTENDED - { VDP_DECODER_PROFILE_H264_EXTENDED, FF_CODEC_TYPE_H264 }, - #endif - #ifdef VDP_DECODER_PROFILE_H264_PROGRESSIVE_HIGH - { VDP_DECODER_PROFILE_H264_PROGRESSIVE_HIGH, FF_CODEC_TYPE_H264 }, - #endif - #ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_HIGH - { VDP_DECODER_PROFILE_H264_CONSTRAINED_HIGH, FF_CODEC_TYPE_H264 }, - #endif - #ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE - { VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE, FF_CODEC_TYPE_H264 }, - #endif - #ifdef VDP_DECODER_PROFILE_VC1_SIMPLE - { VDP_DECODER_PROFILE_VC1_SIMPLE, FF_CODEC_TYPE_VC1 }, - #endif - #ifdef VDP_DECODER_PROFILE_VC1_MAIN - { VDP_DECODER_PROFILE_VC1_MAIN, FF_CODEC_TYPE_VC1 }, - #endif - #ifdef VDP_DECODER_PROFILE_VC1_ADVANCED - { VDP_DECODER_PROFILE_VC1_ADVANCED, FF_CODEC_TYPE_VC1 }, - #endif - #ifdef VDP_DECODER_PROFILE_HEVC_MAIN - { VDP_DECODER_PROFILE_HEVC_MAIN, FF_CODEC_TYPE_HEVC }, - #endif - #ifdef VDP_DECODER_PROFILE_HEVC_MAIN_10 - { VDP_DECODER_PROFILE_HEVC_MAIN_10, FF_CODEC_TYPE_HEVC }, - #endif - #ifdef VDP_DECODER_PROFILE_HEVC_MAIN_STILL - { VDP_DECODER_PROFILE_HEVC_MAIN_STILL, FF_CODEC_TYPE_HEVC }, - #endif - #ifdef VDP_DECODER_PROFILE_HEVC_MAIN_12 - { VDP_DECODER_PROFILE_HEVC_MAIN_12, FF_CODEC_TYPE_HEVC }, - #endif - #ifdef VDP_DECODER_PROFILE_HEVC_MAIN_444 - { VDP_DECODER_PROFILE_HEVC_MAIN_444, FF_CODEC_TYPE_HEVC }, - #endif - #ifdef VDP_DECODER_PROFILE_HEVC_MAIN_444_10 - { VDP_DECODER_PROFILE_HEVC_MAIN_444_10, FF_CODEC_TYPE_HEVC }, - #endif - #ifdef VDP_DECODER_PROFILE_HEVC_MAIN_444_12 - { VDP_DECODER_PROFILE_HEVC_MAIN_444_12, FF_CODEC_TYPE_HEVC }, - #endif - #ifdef VDP_DECODER_PROFILE_VP9_PROFILE_0 - { VDP_DECODER_PROFILE_VP9_PROFILE_0, FF_CODEC_TYPE_VP9 }, - #endif - #ifdef VDP_DECODER_PROFILE_VP9_PROFILE_1 - { VDP_DECODER_PROFILE_VP9_PROFILE_1, FF_CODEC_TYPE_VP9 }, - #endif - #ifdef VDP_DECODER_PROFILE_VP9_PROFILE_2 - { VDP_DECODER_PROFILE_VP9_PROFILE_2, FF_CODEC_TYPE_VP9 }, - #endif - #ifdef VDP_DECODER_PROFILE_VP9_PROFILE_3 - { VDP_DECODER_PROFILE_VP9_PROFILE_3, FF_CODEC_TYPE_VP9 }, - #endif - #ifdef VDP_DECODER_PROFILE_AV1_MAIN - { VDP_DECODER_PROFILE_AV1_MAIN, FF_CODEC_TYPE_AV1 }, - #endif - #ifdef VDP_DECODER_PROFILE_AV1_HIGH - { VDP_DECODER_PROFILE_AV1_HIGH, FF_CODEC_TYPE_AV1 }, - #endif - #ifdef VDP_DECODER_PROFILE_AV1_PROFESSIONAL - { VDP_DECODER_PROFILE_AV1_PROFESSIONAL, FF_CODEC_TYPE_AV1 }, - #endif + { 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 + { 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 + { 15, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX4_MOBILE + { 16, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX4_HOME_THEATER + { 17, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX4_HD_1080P + { 18, FF_CODEC_TYPE_DIVX_XVID }, // VDP_DECODER_PROFILE_DIVX5_QMOBILE + { 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 + { 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 + { 103, FF_CODEC_TYPE_HEVC }, // VDP_DECODER_PROFILE_HEVC_MAIN_12 + { 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(FFlist* result) { +static const char* ffDetectCodecByVdpau(FFCodecOptions* options, FFlist* result) { + if (options->showType == FF_CODEC_SHOW_TYPE_DECODER) { + return "VDPAU only supports decoding"; + } + FF_LIBRARY_LOAD_MESSAGE(libX11, "libX11" FF_LIBRARY_EXTENSION, 6) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XOpenDisplay) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libX11, XCloseDisplay) @@ -529,19 +459,19 @@ static const char* ffDetectCodecByVdpau(FFlist* result) { } #endif -const char* ffDetectCodecNative(FF_A_UNUSED FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) { +const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) { FF_SUPPRESS_IO(); #if FF_CODEC_HAVE_VA bool vaInitialized = false; - const char* vaError = ffDetectCodecByVa(result, &vaInitialized); + const char* vaError = ffDetectCodecByVa(options, result, &vaInitialized); if (vaError == NULL && vaInitialized) { return NULL; } #endif #if FF_CODEC_HAVE_VDPAU - return ffDetectCodecByVdpau(result); + return ffDetectCodecByVdpau(options, result); #endif return "Fastfetch was built without DRM / VA-API / VDPAU headers"; diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index d8a267f74..4de76f491 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -159,6 +159,22 @@ void ffParseCodecJsonObject(FFCodecOptions* options, yyjson_val* module) { continue; } + if (unsafe_yyjson_equals_str(key, "showType")) { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){ + { "encoder", FF_CODEC_SHOW_TYPE_ENCODER }, + { "decoder", FF_CODEC_SHOW_TYPE_DECODER }, + { "both", FF_CODEC_SHOW_TYPE_BOTH }, + {}, + }); + if (error) { + ffPrintError(FF_CODEC_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + } else { + options->showType = (FFCodecShowType) value; + } + continue; + } + ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -167,6 +183,20 @@ void ffGenerateCodecJsonConfig(FFCodecOptions* options, yyjson_mut_doc* doc, yyj ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); yyjson_mut_obj_add_bool(doc, module, "splitGPU", options->splitGPU); yyjson_mut_obj_add_bool(doc, module, "useVulkan", options->useVulkan); + switch (options->showType) { + case FF_CODEC_SHOW_TYPE_ENCODER: + yyjson_mut_obj_add_str(doc, module, "showType", "encoder"); + break; + case FF_CODEC_SHOW_TYPE_DECODER: + yyjson_mut_obj_add_str(doc, module, "showType", "decoder"); + break; + case FF_CODEC_SHOW_TYPE_BOTH: + yyjson_mut_obj_add_str(doc, module, "showType", "both"); + break; + default: + break; + } + } bool ffGenerateCodecJsonResult(FFCodecOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { @@ -208,6 +238,7 @@ void ffInitCodecOptions(FFCodecOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰈫"); options->splitGPU = false; options->useVulkan = false; + options->showType = FF_CODEC_SHOW_TYPE_BOTH; } void ffDestroyCodecOptions(FFCodecOptions* options) { diff --git a/src/modules/codec/option.h b/src/modules/codec/option.h index f4db5c481..bcc920127 100644 --- a/src/modules/codec/option.h +++ b/src/modules/codec/option.h @@ -2,10 +2,19 @@ #include "common/option.h" +typedef enum FF_A_PACKED FFCodecShowType { + FF_CODEC_SHOW_TYPE_NONE = 0, + FF_CODEC_SHOW_TYPE_ENCODER = 1 << 0, + FF_CODEC_SHOW_TYPE_DECODER = 1 << 1, + FF_CODEC_SHOW_TYPE_BOTH = FF_CODEC_SHOW_TYPE_ENCODER | FF_CODEC_SHOW_TYPE_DECODER, + FF_CODEC_SHOW_TYPE_FORCE_UNSIGNED = UINT8_MAX, +} FFCodecShowType; + typedef struct FFCodecOptions { FFModuleArgs moduleArgs; bool splitGPU; bool useVulkan; + FFCodecShowType showType; } FFCodecOptions; static_assert(sizeof(FFCodecOptions) <= FF_OPTION_MAX_SIZE, "FFCodecOptions size exceeds maximum allowed size");