Decoder: renames to Codec and adds encoders detection support

This commit is contained in:
Carter Li
2026-05-31 13:16:24 +08:00
committed by 李通洲
parent ae5132c388
commit 473a08d85c
15 changed files with 476 additions and 378 deletions
+10 -10
View File
@@ -463,6 +463,7 @@ set(LIBFASTFETCH_SRC
src/modules/btrfs/btrfs.c
src/modules/camera/camera.c
src/modules/chassis/chassis.c
src/modules/codec/codec.c
src/modules/colors/colors.c
src/modules/cpu/cpu.c
src/modules/cpucache/cpucache.c
@@ -471,7 +472,6 @@ set(LIBFASTFETCH_SRC
src/modules/custom/custom.c
src/modules/command/command.c
src/modules/datetime/datetime.c
src/modules/decoder/decoder.c
src/modules/de/de.c
src/modules/disk/disk.c
src/modules/diskio/diskio.c
@@ -550,11 +550,11 @@ if(LINUX)
src/detection/brightness/brightness_linux.c
src/detection/btrfs/btrfs_linux.c
src/detection/chassis/chassis_linux.c
src/detection/codec/codec_linux.c
src/detection/cpu/cpu_linux.c
src/detection/cpucache/cpucache_linux.c
src/detection/cpuusage/cpuusage_linux.c
src/detection/cursor/cursor_linux.c
src/detection/decoder/decoder_linux.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/bluetoothradio/bluetoothradio_linux.c
src/detection/disk/disk_linux.c
@@ -712,11 +712,11 @@ elseif(FreeBSD)
src/detection/brightness/brightness_bsd.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_bsd.c
src/detection/codec/codec_linux.c
src/detection/cpu/cpu_bsd.c
src/detection/cpucache/cpucache_shared.c
src/detection/cpuusage/cpuusage_bsd.c
src/detection/cursor/cursor_linux.c
src/detection/decoder/decoder_linux.c
src/detection/disk/disk_bsd.c
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_bsd.c
@@ -807,11 +807,11 @@ elseif(NetBSD)
src/detection/brightness/brightness_nbsd.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_nbsd.c
src/detection/codec/codec_linux.c
src/detection/cpu/cpu_nbsd.c
src/detection/cpucache/cpucache_shared.c
src/detection/cpuusage/cpuusage_bsd.c
src/detection/cursor/cursor_linux.c
src/detection/decoder/decoder_linux.c
src/detection/disk/disk_bsd.c
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_nbsd.c
@@ -892,11 +892,11 @@ elseif(OpenBSD)
src/detection/brightness/brightness_obsd.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_windows.c
src/detection/codec/codec_linux.c
src/detection/cpu/cpu_obsd.c
src/detection/cpucache/cpucache_shared.c
src/detection/cpuusage/cpuusage_bsd.c
src/detection/cursor/cursor_linux.c
src/detection/decoder/decoder_linux.c
src/detection/disk/disk_bsd.c
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_obsd.c
@@ -976,11 +976,11 @@ elseif(APPLE)
src/detection/bootmgr/bootmgr_apple.c
src/detection/brightness/brightness_apple.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/codec/codec_apple.c
src/detection/cpu/cpu_apple.c
src/detection/cpucache/cpucache_apple.c
src/detection/cpuusage/cpuusage_apple.c
src/detection/cursor/cursor_apple.m
src/detection/decoder/decoder_apple.m
src/detection/disk/disk_bsd.c
src/detection/dns/dns_apple.c
src/detection/physicaldisk/physicaldisk_apple.c
@@ -1067,11 +1067,11 @@ elseif(WIN32)
src/detection/brightness/brightness_windows.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_windows.c
src/detection/codec/codec_windows.cpp
src/detection/cpu/cpu_windows.c
src/detection/cpucache/cpucache_windows.c
src/detection/cpuusage/cpuusage_windows.c
src/detection/cursor/cursor_windows.c
src/detection/decoder/decoder_windows.cpp
src/detection/disk/disk_windows.c
src/detection/physicaldisk/physicaldisk_windows.c
src/detection/diskio/diskio_windows.c
@@ -1139,7 +1139,7 @@ elseif(SunOS)
src/detection/cursor/cursor_linux.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/decoder/decoder_linux.c
src/detection/codec/codec_linux.c
src/detection/disk/disk_sunos.c
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_sunos.c
@@ -1223,7 +1223,7 @@ elseif(Haiku)
src/detection/cursor/cursor_nosupport.c
src/detection/bluetooth/bluetooth_haiku.cpp
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/decoder/decoder_linux.c
src/detection/codec/codec_linux.c
src/detection/disk/disk_haiku.cpp
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_haiku.c
@@ -1293,8 +1293,8 @@ elseif(GNU)
src/detection/cursor/cursor_linux.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/bluetoothradio/bluetoothradio_linux.c
src/detection/codec/codec_linux.c
src/detection/disk/disk_linux.c
src/detection/decoder/decoder_linux.c
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_nosupport.c
src/detection/physicalmemory/physicalmemory_nosupport.c
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include "fastfetch.h"
#include "modules/codec/option.h"
typedef enum FF_A_PACKED FFCodecType {
FF_CODEC_TYPE_NONE = 0,
FF_CODEC_TYPE_UNKNOWN = UINT32_C(1) << 0,
FF_CODEC_TYPE_H261 = UINT32_C(1) << 1,
FF_CODEC_TYPE_H263 = UINT32_C(1) << 2,
FF_CODEC_TYPE_MJPEG = UINT32_C(1) << 3,
FF_CODEC_TYPE_MPEG1 = UINT32_C(1) << 4,
FF_CODEC_TYPE_MPEG2 = UINT32_C(1) << 5,
FF_CODEC_TYPE_DIVX_XVID = UINT32_C(1) << 6,
FF_CODEC_TYPE_H264 = UINT32_C(1) << 7,
FF_CODEC_TYPE_WMV8 = UINT32_C(1) << 8,
FF_CODEC_TYPE_WMV9 = UINT32_C(1) << 9,
FF_CODEC_TYPE_VC1 = UINT32_C(1) << 10,
FF_CODEC_TYPE_VP8 = UINT32_C(1) << 11,
FF_CODEC_TYPE_HEVC = UINT32_C(1) << 12,
FF_CODEC_TYPE_VP9 = UINT32_C(1) << 13,
FF_CODEC_TYPE_AV1 = UINT32_C(1) << 14,
FF_CODEC_TYPE_VVC = UINT32_C(1) << 15,
FF_CODEC_TYPE_DOLBY_VISION_HEVC = UINT32_C(1) << 16,
FF_CODEC_TYPE_PRORES = UINT32_C(1) << 17,
FF_CODEC_TYPE_PRORES_RAW = UINT32_C(1) << 18,
FF_CODEC_TYPE_JPEG_XL = UINT32_C(1) << 19,
FF_CODEC_TYPE_MAX = FF_CODEC_TYPE_JPEG_XL,
FF_CODEC_TYPE_FORCE_UNSIGNED = UINT32_MAX,
} FFCodecType;
typedef struct FFCodecResult {
FFstrbuf gpu;
FFCodecType decoders;
FFCodecType encoders;
} FFCodecResult;
const char* ffDetectCodec(FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/);
+95
View File
@@ -0,0 +1,95 @@
#include "codec.h"
#include <VideoToolbox/VideoToolbox.h>
#include "common/apple/cf_helpers.h"
static const struct {
CMVideoCodecType codec;
FFCodecType type;
} FF_CODEC_CODECS[] = {
{ kCMVideoCodecType_H263, FF_CODEC_TYPE_H263 },
{ kCMVideoCodecType_JPEG, FF_CODEC_TYPE_MJPEG },
{ kCMVideoCodecType_JPEG_XL, FF_CODEC_TYPE_JPEG_XL },
{ kCMVideoCodecType_MPEG1Video, FF_CODEC_TYPE_MPEG1 },
{ kCMVideoCodecType_MPEG2Video, FF_CODEC_TYPE_MPEG2 },
{ kCMVideoCodecType_MPEG4Video, FF_CODEC_TYPE_DIVX_XVID },
{ kCMVideoCodecType_H264, FF_CODEC_TYPE_H264 },
{ kCMVideoCodecType_HEVC, FF_CODEC_TYPE_HEVC },
{ kCMVideoCodecType_HEVCWithAlpha, FF_CODEC_TYPE_HEVC },
{ kCMVideoCodecType_DolbyVisionHEVC, FF_CODEC_TYPE_DOLBY_VISION_HEVC },
{ kCMVideoCodecType_DisparityHEVC, FF_CODEC_TYPE_HEVC },
{ kCMVideoCodecType_DepthHEVC, FF_CODEC_TYPE_HEVC },
{ kCMVideoCodecType_VP9, FF_CODEC_TYPE_VP9 },
{ kCMVideoCodecType_AV1, FF_CODEC_TYPE_AV1 },
{ kCMVideoCodecType_AppleProRes4444XQ, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes4444, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422HQ, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422LT, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422Proxy, FF_CODEC_TYPE_PRORES },
{ kCMVideoCodecType_AppleProResRAW, FF_CODEC_TYPE_PRORES_RAW },
{ kCMVideoCodecType_AppleProResRAWHQ, FF_CODEC_TYPE_PRORES_RAW },
};
static FFCodecType ffCodecCodecToType(CMVideoCodecType codec) {
for (uint32_t i = 0; i < ARRAY_SIZE(FF_CODEC_CODECS); ++i) {
if (FF_CODEC_CODECS[i].codec == codec) {
return FF_CODEC_CODECS[i].type;
}
}
return FF_CODEC_TYPE_NONE;
}
static FFCodecType ffCodecDetectEncoders(void) {
CFArrayRef encoderList = NULL;
if (VTCopyVideoEncoderList(NULL, &encoderList) != noErr || !encoderList) {
return FF_CODEC_TYPE_NONE;
}
FFCodecType types = FF_CODEC_TYPE_NONE;
for (uint32_t i = 0; i < CFArrayGetCount(encoderList); ++i) {
CFDictionaryRef encoder = CFArrayGetValueAtIndex(encoderList, i);
bool isHardwareAccelerated;
int codec;
if (ffCfDictGetBool(encoder, CFSTR("IsHardwareAccelerated"), &isHardwareAccelerated) != NULL ||
!isHardwareAccelerated ||
ffCfDictGetInt(encoder, CFSTR("CodecType"), &codec) != NULL) {
continue;
}
types |= ffCodecCodecToType((CMVideoCodecType) codec);
}
return types;
}
static FFCodecType ffCodecDetectDecoders() {
FFCodecType types = FF_CODEC_TYPE_NONE;
for (uint32_t i = 0; i < ARRAY_SIZE(FF_CODEC_CODECS); ++i) {
if (types & FF_CODEC_CODECS[i].type) {
continue;
}
bool supported = VTIsHardwareDecodeSupported(FF_CODEC_CODECS[i].codec);
if (!supported) {
continue;
}
types |= FF_CODEC_CODECS[i].type;
}
return types;
}
const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
FFCodecType decoders = ffCodecDetectDecoders();
FFCodecType encoders = ffCodecDetectEncoders();
if (decoders != FF_CODEC_TYPE_NONE || encoders != FF_CODEC_TYPE_NONE) {
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
ffStrbufInitStatic(&item->gpu, "Default");
item->decoders = decoders;
item->encoders = encoders;
}
return NULL;
}
@@ -1,4 +1,4 @@
#include "decoder.h"
#include "codec.h"
#if FF_HAVE_DRM && FF_HAVE_VA
@@ -13,22 +13,22 @@
#include <va/va_drm.h>
#include <xf86drm.h>
static FFDecoderType ffDecoderProfileToType(VAProfile profile) {
static FFCodecType ffCodecProfileToType(VAProfile profile) {
switch (profile) {
case 11: // VAProfileH263Baseline
return FF_DECODER_TYPE_H263;
return FF_CODEC_TYPE_H263;
case 12: // VAProfileJPEGBaseline
return FF_DECODER_TYPE_MJPEG;
return FF_CODEC_TYPE_MJPEG;
case 0: // VAProfileMPEG2Simple
case 1: // VAProfileMPEG2Main
return FF_DECODER_TYPE_MPEG2;
return FF_CODEC_TYPE_MPEG2;
case 2: // VAProfileMPEG4Simple
case 3: // VAProfileMPEG4AdvancedSimple
case 4: // VAProfileMPEG4Main
return FF_DECODER_TYPE_DIVX_XVID;
return FF_CODEC_TYPE_DIVX_XVID;
case 5: // VAProfileH264Baseline
case 6: // VAProfileH264Main
@@ -38,15 +38,15 @@ static FFDecoderType ffDecoderProfileToType(VAProfile profile) {
case 16: // VAProfileH264StereoHigh
case 36: // VAProfileH264High10
case 40: // VAProfileH264High422
return FF_DECODER_TYPE_H264;
return FF_CODEC_TYPE_H264;
case 8: // VAProfileVC1Simple
case 9: // VAProfileVC1Main
case 10: // VAProfileVC1Advanced
return FF_DECODER_TYPE_VC1;
return FF_CODEC_TYPE_VC1;
case 14: // VAProfileVP8Version0_3
return FF_DECODER_TYPE_VP8;
return FF_CODEC_TYPE_VP8;
case 17: // VAProfileHEVCMain
case 18: // VAProfileHEVCMain10
@@ -60,29 +60,29 @@ static FFDecoderType ffDecoderProfileToType(VAProfile profile) {
case 30: // VAProfileHEVCSccMain10
case 31: // VAProfileHEVCSccMain444
case 34: // VAProfileHEVCSccMain444_10
return FF_DECODER_TYPE_HEVC;
return FF_CODEC_TYPE_HEVC;
case 19: // VAProfileVP9Profile0
case 20: // VAProfileVP9Profile1
case 21: // VAProfileVP9Profile2
case 22: // VAProfileVP9Profile3
return FF_DECODER_TYPE_VP9;
return FF_CODEC_TYPE_VP9;
case 32: // VAProfileAV1Profile0
case 33: // VAProfileAV1Profile1
case 39: // VAProfileAV1Profile2
return FF_DECODER_TYPE_AV1;
return FF_CODEC_TYPE_AV1;
case 37: // VAProfileVVCMain10
case 38: // VAProfileVVCMultilayerMain10
return FF_DECODER_TYPE_VVC;
return FF_CODEC_TYPE_VVC;
default:
return FF_DECODER_TYPE_UNKNOWN;
return FF_CODEC_TYPE_UNKNOWN;
}
}
static bool ffDecoderEntrypointIsDecode(VAEntrypoint entrypoint) {
static bool ffCodecEntrypointIsDecode(VAEntrypoint entrypoint) {
switch (entrypoint) {
case VAEntrypointVLD:
case VAEntrypointIDCT:
@@ -93,13 +93,26 @@ static bool ffDecoderEntrypointIsDecode(VAEntrypoint entrypoint) {
}
}
static bool ffDecoderProfileHasOutput(
static bool ffCodecEntrypointIsEncode(VAEntrypoint entrypoint) {
switch (entrypoint) {
case VAEntrypointEncSlice:
case VAEntrypointEncPicture:
case VAEntrypointEncSliceLP:
case VAEntrypointEncFEI:
return true;
default:
return false;
}
}
static bool ffCodecProfileHasOutput(
VADisplay display,
__typeof__(vaQueryConfigEntrypoints)* ffvaQueryConfigEntrypoints,
__typeof__(vaGetConfigAttributes)* ffvaGetConfigAttributes,
int maxEntrypoints,
VAEntrypoint* entrypoints,
VAProfile profile
VAProfile profile,
bool encode
) {
int numEntrypoints = maxEntrypoints;
if (ffvaQueryConfigEntrypoints(display, profile, entrypoints, &numEntrypoints) != VA_STATUS_SUCCESS) {
@@ -107,7 +120,7 @@ static bool ffDecoderProfileHasOutput(
}
for (int i = 0; i < numEntrypoints; ++i) {
if (!ffDecoderEntrypointIsDecode(entrypoints[i])) {
if (encode ? !ffCodecEntrypointIsEncode(entrypoints[i]) : !ffCodecEntrypointIsDecode(entrypoints[i])) {
continue;
}
@@ -126,7 +139,7 @@ static bool ffDecoderProfileHasOutput(
return false;
}
static void ffDecoderFillGpuName(const drmDevice* dev, const char* path, FFstrbuf* name) {
static void ffCodecFillGpuName(const drmDevice* dev, const char* path, FFstrbuf* name) {
ffStrbufInit(name);
switch (dev->bustype) {
@@ -167,7 +180,7 @@ static void ffDecoderFillGpuName(const drmDevice* dev, const char* path, FFstrbu
}
}
const char* ffDetectDecoder(FF_A_UNUSED FFDecoderOptions* options, FFlist* result /* list of FFDecoderResult */) {
const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
@@ -243,26 +256,45 @@ const char* ffDetectDecoder(FF_A_UNUSED FFDecoderOptions* options, FFlist* resul
continue;
}
FFDecoderType types = FF_DECODER_TYPE_NONE;
FFCodecType decoderTypes = FF_CODEC_TYPE_NONE;
FFCodecType encoderTypes = FF_CODEC_TYPE_NONE;
for (int j = 0; j < numProfiles; ++j) {
if (!ffDecoderProfileHasOutput(
display,
ffvaQueryConfigEntrypoints,
ffvaGetConfigAttributes,
maxEntrypoints,
entrypoints,
profiles[j])) {
bool hasDecoder = ffCodecProfileHasOutput(
display,
ffvaQueryConfigEntrypoints,
ffvaGetConfigAttributes,
maxEntrypoints,
entrypoints,
profiles[j],
false);
bool hasEncoder = ffCodecProfileHasOutput(
display,
ffvaQueryConfigEntrypoints,
ffvaGetConfigAttributes,
maxEntrypoints,
entrypoints,
profiles[j],
true);
if (!hasDecoder && !hasEncoder) {
continue;
}
FFDecoderType type = ffDecoderProfileToType(profiles[j]);
types = (FFDecoderType) ((uint32_t) types | (uint32_t) type);
FFCodecType type = ffCodecProfileToType(profiles[j]);
if (hasDecoder) {
decoderTypes = (FFCodecType) ((uint32_t) decoderTypes | (uint32_t) type);
}
if (hasEncoder) {
encoderTypes = (FFCodecType) ((uint32_t) encoderTypes | (uint32_t) type);
}
}
if (types != FF_DECODER_TYPE_NONE) {
FFDecoderResult* item = FF_LIST_ADD(FFDecoderResult, *result);
ffDecoderFillGpuName(dev, path, &item->gpu);
item->types = types;
if (decoderTypes != FF_CODEC_TYPE_NONE || encoderTypes != FF_CODEC_TYPE_NONE) {
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
ffCodecFillGpuName(dev, path, &item->gpu);
item->decoders = decoderTypes;
item->encoders = encoderTypes;
}
ffvaTerminate(display);
@@ -274,7 +306,7 @@ const char* ffDetectDecoder(FF_A_UNUSED FFDecoderOptions* options, FFlist* resul
#else
const char* ffDetectDecoder(FFDecoderOptions* options, FFlist* result /* list of FFDecoderResult */) {
const char* ffDetectCodec(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
FF_UNUSED(options, result);
return "Fastfetch was built without DRM / VA-API headers";
}
@@ -1,5 +1,5 @@
extern "C" {
#include "decoder.h"
#include "codec.h"
#include "common/library.h"
#include "common/windows/com.h"
#include "common/windows/unicode.h"
@@ -10,7 +10,7 @@ extern "C" {
#include <initguid.h>
#include <dxva.h>
static const DXGI_FORMAT FF_NATIVE_DECODER_FORMATS[] = {
static const DXGI_FORMAT FF_NATIVE_CODEC_FORMATS[] = {
DXGI_FORMAT_420_OPAQUE,
DXGI_FORMAT_NV12,
DXGI_FORMAT_P010,
@@ -23,11 +23,11 @@ static const DXGI_FORMAT FF_NATIVE_DECODER_FORMATS[] = {
DXGI_FORMAT_Y416,
};
static FFDecoderType ffDecoderProfileToType(const GUID& profile) {
static FFCodecType ffCodecProfileToType(const GUID& profile) {
// clang-format off
if (IsEqualGUID(profile, DXVA_ModeH261_A) ||
IsEqualGUID(profile, DXVA_ModeH261_B)) {
return FF_DECODER_TYPE_H261;
return FF_CODEC_TYPE_H261;
}
if (IsEqualGUID(profile, DXVA_ModeH263_A) ||
@@ -36,7 +36,7 @@ static FFDecoderType ffDecoderProfileToType(const GUID& profile) {
IsEqualGUID(profile, DXVA_ModeH263_D) ||
IsEqualGUID(profile, DXVA_ModeH263_E) ||
IsEqualGUID(profile, DXVA_ModeH263_F)) {
return FF_DECODER_TYPE_H263;
return FF_CODEC_TYPE_H263;
}
if (IsEqualGUID(profile, DXVA_ModeMJPEG_VLD_420) ||
@@ -46,12 +46,12 @@ static FFDecoderType ffDecoderProfileToType(const GUID& profile) {
IsEqualGUID(profile, DXVA_ModeJPEG_VLD_420) ||
IsEqualGUID(profile, DXVA_ModeJPEG_VLD_422) ||
IsEqualGUID(profile, DXVA_ModeJPEG_VLD_444)) {
return FF_DECODER_TYPE_MJPEG;
return FF_CODEC_TYPE_MJPEG;
}
if (IsEqualGUID(profile, DXVA_ModeMPEG1_A) ||
IsEqualGUID(profile, DXVA_ModeMPEG1_VLD)) {
return FF_DECODER_TYPE_MPEG1;
return FF_CODEC_TYPE_MPEG1;
}
if (IsEqualGUID(profile, DXVA_ModeMPEG2_A) ||
@@ -59,13 +59,13 @@ static FFDecoderType ffDecoderProfileToType(const GUID& profile) {
IsEqualGUID(profile, DXVA_ModeMPEG2_C) ||
IsEqualGUID(profile, DXVA_ModeMPEG2_D) ||
IsEqualGUID(profile, DXVA_ModeMPEG2and1_VLD)) {
return FF_DECODER_TYPE_MPEG2;
return FF_CODEC_TYPE_MPEG2;
}
if (IsEqualGUID(profile, DXVA_ModeMPEG4pt2_VLD_Simple) ||
IsEqualGUID(profile, DXVA_ModeMPEG4pt2_VLD_AdvSimple_NoGMC) ||
IsEqualGUID(profile, DXVA_ModeMPEG4pt2_VLD_AdvSimple_GMC)) {
return FF_DECODER_TYPE_DIVX_XVID;
return FF_CODEC_TYPE_DIVX_XVID;
}
if (IsEqualGUID(profile, DXVA_ModeH264_E) ||
@@ -74,18 +74,18 @@ static FFDecoderType ffDecoderProfileToType(const GUID& profile) {
IsEqualGUID(profile, DXVA_ModeH264_VLD_Stereo_Progressive_NoFGT) ||
IsEqualGUID(profile, DXVA_ModeH264_VLD_Stereo_NoFGT) ||
IsEqualGUID(profile, DXVA_ModeH264_VLD_Multiview_NoFGT)) {
return FF_DECODER_TYPE_H264;
return FF_CODEC_TYPE_H264;
}
if (IsEqualGUID(profile, DXVA_ModeWMV8_A) ||
IsEqualGUID(profile, DXVA_ModeWMV8_B)) {
return FF_DECODER_TYPE_WMV8;
return FF_CODEC_TYPE_WMV8;
}
if (IsEqualGUID(profile, DXVA_ModeWMV9_A) ||
IsEqualGUID(profile, DXVA_ModeWMV9_B) ||
IsEqualGUID(profile, DXVA_ModeWMV9_C)) {
return FF_DECODER_TYPE_WMV9;
return FF_CODEC_TYPE_WMV9;
}
if (IsEqualGUID(profile, DXVA_ModeVC1_A) ||
@@ -93,11 +93,11 @@ static FFDecoderType ffDecoderProfileToType(const GUID& profile) {
IsEqualGUID(profile, DXVA_ModeVC1_C) ||
IsEqualGUID(profile, DXVA_ModeVC1_D) ||
IsEqualGUID(profile, DXVA_ModeVC1_D2010)) {
return FF_DECODER_TYPE_VC1;
return FF_CODEC_TYPE_VC1;
}
if (IsEqualGUID(profile, DXVA_ModeVP8_VLD)) {
return FF_DECODER_TYPE_VP8;
return FF_CODEC_TYPE_VP8;
}
if (IsEqualGUID(profile, DXVA_ModeHEVC_VLD_Main) ||
@@ -110,12 +110,12 @@ static FFDecoderType ffDecoderProfileToType(const GUID& profile) {
IsEqualGUID(profile, DXVA_ModeHEVC_VLD_Main10_444) ||
IsEqualGUID(profile, DXVA_ModeHEVC_VLD_Main12_444) ||
IsEqualGUID(profile, DXVA_ModeHEVC_VLD_Main16)) {
return FF_DECODER_TYPE_HEVC;
return FF_CODEC_TYPE_HEVC;
}
if (IsEqualGUID(profile, DXVA_ModeVP9_VLD_Profile0) ||
IsEqualGUID(profile, DXVA_ModeVP9_VLD_10bit_Profile2)) {
return FF_DECODER_TYPE_VP9;
return FF_CODEC_TYPE_VP9;
}
if (IsEqualGUID(profile, DXVA_ModeAV1_VLD_Profile0) ||
@@ -123,17 +123,17 @@ static FFDecoderType ffDecoderProfileToType(const GUID& profile) {
IsEqualGUID(profile, DXVA_ModeAV1_VLD_Profile2) ||
IsEqualGUID(profile, DXVA_ModeAV1_VLD_12bit_Profile2) ||
IsEqualGUID(profile, DXVA_ModeAV1_VLD_12bit_Profile2_420)) {
return FF_DECODER_TYPE_AV1;
return FF_CODEC_TYPE_AV1;
}
// clang-format on
return FF_DECODER_TYPE_UNKNOWN;
return FF_CODEC_TYPE_UNKNOWN;
}
static bool ffDecoderProfileHasNativeOutput(ID3D11VideoDevice* videoDevice, const GUID& profile) {
for (uint32_t i = 0; i < ARRAY_SIZE(FF_NATIVE_DECODER_FORMATS); ++i) {
static bool ffCodecProfileHasNativeOutput(ID3D11VideoDevice* videoDevice, const GUID& profile) {
for (uint32_t i = 0; i < ARRAY_SIZE(FF_NATIVE_CODEC_FORMATS); ++i) {
BOOL supported = FALSE;
if (SUCCEEDED(videoDevice->CheckVideoDecoderFormat(&profile, FF_NATIVE_DECODER_FORMATS[i], &supported)) && supported) {
if (SUCCEEDED(videoDevice->CheckVideoDecoderFormat(&profile, FF_NATIVE_CODEC_FORMATS[i], &supported)) && supported) {
return true;
}
}
@@ -141,7 +141,7 @@ static bool ffDecoderProfileHasNativeOutput(ID3D11VideoDevice* videoDevice, cons
return false;
}
const char* ffDetectDecoder(FF_A_UNUSED FFDecoderOptions* options, FFlist* result /*list of FFDecoderResult*/) {
const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/) {
FF_LIBRARY_LOAD_MESSAGE(dxgi, "dxgi" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(dxgi, CreateDXGIFactory1)
FF_LIBRARY_LOAD_MESSAGE(d3d11, "d3d11" FF_LIBRARY_EXTENSION, 1)
@@ -197,7 +197,7 @@ const char* ffDetectDecoder(FF_A_UNUSED FFDecoderOptions* options, FFlist* resul
continue;
}
FFDecoderResult* gpuResult = nullptr;
FFCodecResult* gpuResult = nullptr;
UINT profileCount = videoDevice->GetVideoDecoderProfileCount();
for (UINT profileIndex = 0; profileIndex < profileCount; ++profileIndex) {
GUID profile;
@@ -205,16 +205,17 @@ const char* ffDetectDecoder(FF_A_UNUSED FFDecoderOptions* options, FFlist* resul
continue;
}
if (!ffDecoderProfileHasNativeOutput(videoDevice, profile)) {
if (!ffCodecProfileHasNativeOutput(videoDevice, profile)) {
continue;
}
if (!gpuResult) {
gpuResult = FF_LIST_ADD(FFDecoderResult, *result);
gpuResult = FF_LIST_ADD(FFCodecResult, *result);
ffStrbufInitWS(&gpuResult->gpu, desc.Description);
gpuResult->types = FF_DECODER_TYPE_NONE;
gpuResult->decoders = FF_CODEC_TYPE_NONE;
gpuResult->encoders = FF_CODEC_TYPE_NONE;
}
gpuResult->types = (FFDecoderType) (((uint32_t) gpuResult->types) | ((uint32_t) ffDecoderProfileToType(profile)));
gpuResult->decoders = (FFCodecType) (((uint32_t) gpuResult->decoders) | ((uint32_t) ffCodecProfileToType(profile)));
}
}
-37
View File
@@ -1,37 +0,0 @@
#pragma once
#include "fastfetch.h"
#include "modules/decoder/option.h"
typedef enum FF_A_PACKED FFDecoderType {
FF_DECODER_TYPE_NONE = 0,
FF_DECODER_TYPE_UNKNOWN = UINT32_C(1) << 0,
FF_DECODER_TYPE_H261 = UINT32_C(1) << 1,
FF_DECODER_TYPE_H263 = UINT32_C(1) << 2,
FF_DECODER_TYPE_MJPEG = UINT32_C(1) << 3,
FF_DECODER_TYPE_MPEG1 = UINT32_C(1) << 4,
FF_DECODER_TYPE_MPEG2 = UINT32_C(1) << 5,
FF_DECODER_TYPE_DIVX_XVID = UINT32_C(1) << 6,
FF_DECODER_TYPE_H264 = UINT32_C(1) << 7,
FF_DECODER_TYPE_WMV8 = UINT32_C(1) << 8,
FF_DECODER_TYPE_WMV9 = UINT32_C(1) << 9,
FF_DECODER_TYPE_VC1 = UINT32_C(1) << 10,
FF_DECODER_TYPE_VP8 = UINT32_C(1) << 11,
FF_DECODER_TYPE_HEVC = UINT32_C(1) << 12,
FF_DECODER_TYPE_VP9 = UINT32_C(1) << 13,
FF_DECODER_TYPE_AV1 = UINT32_C(1) << 14,
FF_DECODER_TYPE_VVC = UINT32_C(1) << 15,
FF_DECODER_TYPE_DOLBY_VISION_HEVC = UINT32_C(1) << 16,
FF_DECODER_TYPE_PRORES = UINT32_C(1) << 17,
FF_DECODER_TYPE_PRORES_RAW = UINT32_C(1) << 18,
FF_DECODER_TYPE_JPEG_XL = UINT32_C(1) << 19,
FF_DECODER_TYPE_MAX = FF_DECODER_TYPE_JPEG_XL,
FF_DECODER_TYPE_FORCE_UNSIGNED = UINT32_MAX,
} FFDecoderType;
typedef struct FFDecoderResult {
FFstrbuf gpu;
FFDecoderType types;
} FFDecoderResult;
const char* ffDetectDecoder(FFDecoderOptions* options, FFlist* result /*list of FFDecoderResult*/);
-51
View File
@@ -1,51 +0,0 @@
#include "decoder.h"
#import <Metal/MTLDevice.h>
#import <VideoToolbox/VideoToolbox.h>
const char* ffDetectDecoder(FF_A_UNUSED FFDecoderOptions* options, FFlist* result /* list of FFDecoderResult */) {
static const struct {
CMVideoCodecType codec;
FFDecoderType type;
} codecs[] = {
{ kCMVideoCodecType_H263, FF_DECODER_TYPE_H263 },
{ kCMVideoCodecType_JPEG, FF_DECODER_TYPE_MJPEG },
{ kCMVideoCodecType_JPEG_XL, FF_DECODER_TYPE_JPEG_XL },
{ kCMVideoCodecType_MPEG1Video, FF_DECODER_TYPE_MPEG1 },
{ kCMVideoCodecType_MPEG2Video, FF_DECODER_TYPE_MPEG2 },
{ kCMVideoCodecType_MPEG4Video, FF_DECODER_TYPE_DIVX_XVID },
{ kCMVideoCodecType_H264, FF_DECODER_TYPE_H264 },
{ kCMVideoCodecType_HEVC, FF_DECODER_TYPE_HEVC },
{ kCMVideoCodecType_HEVCWithAlpha, FF_DECODER_TYPE_HEVC },
{ kCMVideoCodecType_DolbyVisionHEVC, FF_DECODER_TYPE_DOLBY_VISION_HEVC },
{ kCMVideoCodecType_DisparityHEVC, FF_DECODER_TYPE_HEVC },
{ kCMVideoCodecType_DepthHEVC, FF_DECODER_TYPE_HEVC },
{ kCMVideoCodecType_VP9, FF_DECODER_TYPE_VP9 },
{ kCMVideoCodecType_AV1, FF_DECODER_TYPE_AV1 },
{ kCMVideoCodecType_AppleProRes4444XQ, FF_DECODER_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes4444, FF_DECODER_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422HQ, FF_DECODER_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422, FF_DECODER_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422LT, FF_DECODER_TYPE_PRORES },
{ kCMVideoCodecType_AppleProRes422Proxy, FF_DECODER_TYPE_PRORES },
{ kCMVideoCodecType_AppleProResRAW, FF_DECODER_TYPE_PRORES_RAW },
{ kCMVideoCodecType_AppleProResRAWHQ, FF_DECODER_TYPE_PRORES_RAW },
};
FFDecoderType types = FF_DECODER_TYPE_NONE;
for (uint32_t i = 0; i < ARRAY_SIZE(codecs); ++i) {
if (types & codecs[i].type || !VTIsHardwareDecodeSupported(codecs[i].codec)) {
continue;
}
types |= codecs[i].type;
}
if (types != FF_DECODER_TYPE_NONE) {
FFDecoderResult* item = FF_LIST_ADD(FFDecoderResult, *result);
ffStrbufInitS(&item->gpu, MTLCreateSystemDefaultDevice().name.UTF8String ?: "VideoToolbox");
item->types = types;
}
return NULL;
}
+214
View File
@@ -0,0 +1,214 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/codec/codec.h"
#include "modules/codec/codec.h"
static const char* ffCodecTypeToString(FFCodecType type) {
switch (type) {
case FF_CODEC_TYPE_H261:
return "H.261";
case FF_CODEC_TYPE_H263:
return "H.263";
case FF_CODEC_TYPE_MJPEG:
return "MJPEG";
case FF_CODEC_TYPE_MPEG1:
return "MPEG-1";
case FF_CODEC_TYPE_MPEG2:
return "MPEG-2";
case FF_CODEC_TYPE_DIVX_XVID:
return "DivX / Xvid";
case FF_CODEC_TYPE_H264:
return "H.264";
case FF_CODEC_TYPE_WMV8:
return "WMV-8";
case FF_CODEC_TYPE_WMV9:
return "WMV-9";
case FF_CODEC_TYPE_VC1:
return "VC-1";
case FF_CODEC_TYPE_VP8:
return "VP8";
case FF_CODEC_TYPE_HEVC:
return "HEVC / H.265";
case FF_CODEC_TYPE_VP9:
return "VP9";
case FF_CODEC_TYPE_AV1:
return "AV1";
case FF_CODEC_TYPE_VVC:
return "VVC / H.266";
case FF_CODEC_TYPE_DOLBY_VISION_HEVC:
return "Dolby Vision (HEVC)";
case FF_CODEC_TYPE_PRORES:
return "Apple ProRes";
case FF_CODEC_TYPE_PRORES_RAW:
return "Apple ProRes RAW";
case FF_CODEC_TYPE_JPEG_XL:
return "JPEG XL";
case FF_CODEC_TYPE_UNKNOWN:
default:
return "Unknown";
}
}
static void ffCodecAppendTypeList(FFlist* list, FFCodecType types) {
for (FFCodecType type = FF_CODEC_TYPE_UNKNOWN; type <= FF_CODEC_TYPE_MAX; type <<= 1) {
if ((types & type) == 0) {
continue;
}
ffStrbufInitStatic(FF_LIST_ADD(FFstrbuf, *list), ffCodecTypeToString(type));
}
}
static void ffCodecAppendTypeJoined(FFstrbuf* buffer, FFCodecType types) {
for (FFCodecType type = FF_CODEC_TYPE_UNKNOWN; type <= FF_CODEC_TYPE_MAX; type <<= 1) {
if ((types & type) == 0) {
continue;
}
if (buffer->length > 0) {
ffStrbufAppendS(buffer, ", ");
}
ffStrbufAppendS(buffer, ffCodecTypeToString(type));
}
}
static void ffDestroyCodecResults(FFlist* result) {
FF_LIST_FOR_EACH (FFCodecResult, item, *result) {
ffStrbufDestroy(&item->gpu);
}
}
static void printCodec(const FFCodecOptions* options, const FFCodecResult* result, uint8_t index) {
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
if (options->moduleArgs.key.length == 0) {
ffStrbufSetF(&key, "%s (%s)", FF_CODEC_MODULE_NAME, result->gpu.chars);
} else {
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]){
FF_ARG(result->gpu, "gpu"),
FF_ARG(options->moduleArgs.keyIcon, "icon"),
FF_ARG(index, "index"),
}));
}
if (options->moduleArgs.outputFormat.length == 0) {
FF_STRBUF_AUTO_DESTROY decodersJoined = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY encodersJoined = ffStrbufCreate();
ffCodecAppendTypeJoined(&decodersJoined, result->decoders);
ffCodecAppendTypeJoined(&encodersJoined, result->encoders);
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
printf("Decode: %s | Encode: %s", decodersJoined.length ? decodersJoined.chars : "None", encodersJoined.length ? encodersJoined.chars : "None");
putchar('\n');
} else {
FF_LIST_AUTO_DESTROY decoders = ffListCreate(); // Use list instead of pre-joined string for qjs and lua
FF_LIST_AUTO_DESTROY encoders = ffListCreate();
ffCodecAppendTypeList(&decoders, result->decoders);
ffCodecAppendTypeList(&encoders, result->encoders);
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]){
FF_ARG(result->gpu, "gpu"),
FF_ARG(decoders, "decoders"),
FF_ARG(encoders, "encoders"),
FF_ARG(decoders, "types"),
}));
// No need to destroy strings in lists, as they are static strings
}
}
bool ffPrintCodec(FFCodecOptions* options) {
FF_LIST_AUTO_DESTROY result = ffListCreate();
const char* error = ffDetectCodec(NULL, &result);
if (error) {
ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
return false;
}
if (result.length == 0) {
ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No hardware video acceleration found");
return false;
}
for (uint32_t i = 0; i < result.length; ++i) {
uint8_t index = (uint8_t) (result.length == 1 ? 0 : i + 1);
printCodec(options, FF_LIST_GET(FFCodecResult, result, i), index);
}
ffDestroyCodecResults(&result);
return true;
}
void ffParseCodecJsonObject(FFCodecOptions* options, yyjson_val* module) {
yyjson_val *key, *val;
size_t idx, max;
yyjson_obj_foreach (module, idx, max, key, val) {
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
continue;
}
ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
}
}
void ffGenerateCodecJsonConfig(FFCodecOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
}
bool ffGenerateCodecJsonResult(FF_A_UNUSED FFCodecOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
FF_LIST_AUTO_DESTROY result = ffListCreate();
const char* error = ffDetectCodec(NULL, &result);
if (error) {
yyjson_mut_obj_add_str(doc, module, "error", error);
return false;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH (FFCodecResult, item, result) {
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "gpu", &item->gpu);
yyjson_mut_val* decoders = yyjson_mut_obj_add_arr(doc, obj, "decoders");
yyjson_mut_val* encoders = yyjson_mut_obj_add_arr(doc, obj, "encoders");
yyjson_mut_val* types = yyjson_mut_obj_add_arr(doc, obj, "types"); // compatibility alias for decoders
for (FFCodecType type = FF_CODEC_TYPE_UNKNOWN; type <= FF_CODEC_TYPE_MAX; type <<= 1) {
if ((item->decoders & type) != 0) {
const char* name = ffCodecTypeToString(type);
yyjson_mut_arr_add_str(doc, decoders, name);
yyjson_mut_arr_add_str(doc, types, name);
}
if ((item->encoders & type) != 0) {
yyjson_mut_arr_add_str(doc, encoders, ffCodecTypeToString(type));
}
}
}
ffDestroyCodecResults(&result);
return true;
}
void ffInitCodecOptions(FFCodecOptions* options) {
ffOptionInitModuleArg(&options->moduleArgs, "󰚔");
}
void ffDestroyCodecOptions(FFCodecOptions* options) {
ffOptionDestroyModuleArg(&options->moduleArgs);
}
FFModuleBaseInfo ffCodecModuleInfo = {
.name = FF_CODEC_MODULE_NAME,
.description = "Print hardware video acceleration codec types (decode / encode)",
.initOptions = (void*) ffInitCodecOptions,
.destroyOptions = (void*) ffDestroyCodecOptions,
.parseJsonObject = (void*) ffParseCodecJsonObject,
.printModule = (void*) ffPrintCodec,
.generateJsonResult = (void*) ffGenerateCodecJsonResult,
.generateJsonConfig = (void*) ffGenerateCodecJsonConfig,
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]){
{ "GPU name", "gpu" },
{ "Decoder codec type list", "decoders" },
{ "Encoder codec type list", "encoders" },
{ "Compatibility alias of decoders", "types" },
}))
};
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include "option.h"
#define FF_CODEC_MODULE_NAME "Codec"
bool ffPrintCodec(FFCodecOptions* options);
void ffInitCodecOptions(FFCodecOptions* options);
void ffDestroyCodecOptions(FFCodecOptions* options);
extern FFModuleBaseInfo ffCodecModuleInfo;
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "common/option.h"
typedef struct FFCodecOptions {
FFModuleArgs moduleArgs;
} FFCodecOptions;
static_assert(sizeof(FFCodecOptions) <= FF_OPTION_MAX_SIZE, "FFCodecOptions size exceeds maximum allowed size");
-194
View File
@@ -1,194 +0,0 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/decoder/decoder.h"
#include "modules/decoder/decoder.h"
static const char* ffDecoderTypeToString(FFDecoderType type) {
switch (type) {
case FF_DECODER_TYPE_H261:
return "H.261";
case FF_DECODER_TYPE_H263:
return "H.263";
case FF_DECODER_TYPE_MJPEG:
return "MJPEG";
case FF_DECODER_TYPE_MPEG1:
return "MPEG-1";
case FF_DECODER_TYPE_MPEG2:
return "MPEG-2";
case FF_DECODER_TYPE_DIVX_XVID:
return "DivX / Xvid";
case FF_DECODER_TYPE_H264:
return "H.264";
case FF_DECODER_TYPE_WMV8:
return "WMV-8";
case FF_DECODER_TYPE_WMV9:
return "WMV-9";
case FF_DECODER_TYPE_VC1:
return "VC-1";
case FF_DECODER_TYPE_VP8:
return "VP8";
case FF_DECODER_TYPE_HEVC:
return "HEVC / H.265";
case FF_DECODER_TYPE_VP9:
return "VP9";
case FF_DECODER_TYPE_AV1:
return "AV1";
case FF_DECODER_TYPE_VVC:
return "VVC / H.266";
case FF_DECODER_TYPE_DOLBY_VISION_HEVC:
return "Dolby Vision (HEVC)";
case FF_DECODER_TYPE_PRORES:
return "Apple ProRes";
case FF_DECODER_TYPE_PRORES_RAW:
return "Apple ProRes RAW";
case FF_DECODER_TYPE_JPEG_XL:
return "JPEG XL";
case FF_DECODER_TYPE_UNKNOWN:
default:
return "Unknown";
}
}
static void ffDestroyDecoderResults(FFlist* result) {
FF_LIST_FOR_EACH (FFDecoderResult, item, *result) {
ffStrbufDestroy(&item->gpu);
}
}
static void printDecoder(const FFDecoderOptions* options, const FFDecoderResult* decoder, uint8_t index) {
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
if (options->moduleArgs.key.length == 0) {
ffStrbufSetF(&key, "%s (%s)", FF_DECODER_MODULE_NAME, decoder->gpu.chars);
} else {
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]){
FF_ARG(decoder->gpu, "gpu"),
FF_ARG(options->moduleArgs.keyIcon, "icon"),
FF_ARG(index, "index"),
}));
}
if (options->moduleArgs.outputFormat.length == 0) {
FF_STRBUF_AUTO_DESTROY typesJoined = ffStrbufCreate();
for (FFDecoderType type = FF_DECODER_TYPE_UNKNOWN; type <= FF_DECODER_TYPE_MAX; type <<= 1) {
if ((decoder->types & type) == 0) {
continue;
}
if (typesJoined.length > 0) {
ffStrbufAppendS(&typesJoined, ", ");
}
ffStrbufAppendS(&typesJoined, ffDecoderTypeToString(type));
}
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
if (typesJoined.length > 0) {
ffStrbufWriteTo(&typesJoined, stdout);
}
putchar('\n');
} else {
FF_LIST_AUTO_DESTROY types = ffListCreate(); // Use list instead of pre-joined string for qjs and lua
for (FFDecoderType type = FF_DECODER_TYPE_UNKNOWN; type <= FF_DECODER_TYPE_MAX; type <<= 1) {
if ((decoder->types & type) == 0) {
continue;
}
ffStrbufInitStatic(FF_LIST_ADD(FFstrbuf, types), ffDecoderTypeToString(type));
}
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]){
FF_ARG(decoder->gpu, "gpu"),
FF_ARG(types, "types"),
}));
// No need to destroy strings in types list, as they are static strings
}
}
bool ffPrintDecoder(FFDecoderOptions* options) {
FF_LIST_AUTO_DESTROY result = ffListCreate();
const char* error = ffDetectDecoder(NULL, &result);
if (error) {
ffPrintError(FF_DECODER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
return false;
}
if (result.length == 0) {
ffPrintError(FF_DECODER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No hardware decoder found");
return false;
}
for (uint32_t i = 0; i < result.length; ++i) {
uint8_t index = (uint8_t) (result.length == 1 ? 0 : i + 1);
printDecoder(options, FF_LIST_GET(FFDecoderResult, result, i), index);
}
ffDestroyDecoderResults(&result);
return true;
}
void ffParseDecoderJsonObject(FFDecoderOptions* options, yyjson_val* module) {
yyjson_val *key, *val;
size_t idx, max;
yyjson_obj_foreach (module, idx, max, key, val) {
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
continue;
}
ffPrintError(FF_DECODER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
}
}
void ffGenerateDecoderJsonConfig(FFDecoderOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
}
bool ffGenerateDecoderJsonResult(FF_A_UNUSED FFDecoderOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
FF_LIST_AUTO_DESTROY result = ffListCreate();
const char* error = ffDetectDecoder(NULL, &result);
if (error) {
yyjson_mut_obj_add_str(doc, module, "error", error);
return false;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH (FFDecoderResult, item, result) {
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "gpu", &item->gpu);
yyjson_mut_val* types = yyjson_mut_obj_add_arr(doc, obj, "types");
for (FFDecoderType type = FF_DECODER_TYPE_UNKNOWN; type <= FF_DECODER_TYPE_MAX; type <<= 1) {
if ((item->types & type) == 0) {
continue;
}
yyjson_mut_arr_add_str(doc, types, ffDecoderTypeToString(type));
}
}
ffDestroyDecoderResults(&result);
return true;
}
void ffInitDecoderOptions(FFDecoderOptions* options) {
ffOptionInitModuleArg(&options->moduleArgs, "󰚔");
}
void ffDestroyDecoderOptions(FFDecoderOptions* options) {
ffOptionDestroyModuleArg(&options->moduleArgs);
}
FFModuleBaseInfo ffDecoderModuleInfo = {
.name = FF_DECODER_MODULE_NAME,
.description = "Print hardware decoder types grouped by GPU",
.initOptions = (void*) ffInitDecoderOptions,
.destroyOptions = (void*) ffDestroyDecoderOptions,
.parseJsonObject = (void*) ffParseDecoderJsonObject,
.printModule = (void*) ffPrintDecoder,
.generateJsonResult = (void*) ffGenerateDecoderJsonResult,
.generateJsonConfig = (void*) ffGenerateDecoderJsonConfig,
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]){
{ "GPU name", "gpu" },
{ "Decoder types, comma-separated", "types" },
}))
};
-11
View File
@@ -1,11 +0,0 @@
#pragma once
#include "option.h"
#define FF_DECODER_MODULE_NAME "Decoder"
bool ffPrintDecoder(FFDecoderOptions* options);
void ffInitDecoderOptions(FFDecoderOptions* options);
void ffDestroyDecoderOptions(FFDecoderOptions* options);
extern FFModuleBaseInfo ffDecoderModuleInfo;
-9
View File
@@ -1,9 +0,0 @@
#pragma once
#include "common/option.h"
typedef struct FFDecoderOptions {
FFModuleArgs moduleArgs;
} FFDecoderOptions;
static_assert(sizeof(FFDecoderOptions) <= FF_OPTION_MAX_SIZE, "FFDecoderOptions size exceeds maximum allowed size");
+3 -3
View File
@@ -47,6 +47,9 @@ static FFModuleBaseInfo* C[] = {
#if !FF_MODULE_DISABLE_CHASSIS
&ffChassisModuleInfo,
#endif
#if !FF_MODULE_DISABLE_CODEC
&ffCodecModuleInfo,
#endif
#if !FF_MODULE_DISABLE_COMMAND
&ffCommandModuleInfo,
#endif
@@ -78,9 +81,6 @@ static FFModuleBaseInfo* D[] = {
#if !FF_MODULE_DISABLE_DE
&ffDEModuleInfo,
#endif
#if !FF_MODULE_DISABLE_DECODER
&ffDecoderModuleInfo,
#endif
#if !FF_MODULE_DISABLE_DISPLAY
&ffDisplayModuleInfo,
#endif
+1 -1
View File
@@ -15,11 +15,11 @@
#include "modules/cpucache/cpucache.h"
#include "modules/cpuusage/cpuusage.h"
#include "modules/command/command.h"
#include "modules/codec/codec.h"
#include "modules/colors/colors.h"
#include "modules/cursor/cursor.h"
#include "modules/custom/custom.h"
#include "modules/datetime/datetime.h"
#include "modules/decoder/decoder.h"
#include "modules/disk/disk.h"
#include "modules/diskio/diskio.h"
#include "modules/display/display.h"