mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Codec: adds vulkan support
This commit is contained in:
@@ -423,6 +423,8 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/bluetoothradio/bluetoothradio.c
|
||||
src/detection/bootmgr/bootmgr.c
|
||||
src/detection/chassis/chassis.c
|
||||
src/detection/codec/codec.c
|
||||
src/detection/codec/codec_vulkan.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpuusage/cpuusage.c
|
||||
src/detection/command/command.c
|
||||
|
||||
@@ -1909,6 +1909,11 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"useVulkan": {
|
||||
"description": "Whether to use Vulkan for codec detection instead of other platform-specific APIs",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "codec.h"
|
||||
|
||||
const char* ffDetectCodec(FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/) {
|
||||
if (options->useVulkan) {
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
return ffDetectCodecVulkan(result);
|
||||
#else
|
||||
FF_UNUSED(result);
|
||||
return "Fastfetch was built without Vulkan support";
|
||||
#endif
|
||||
}
|
||||
|
||||
return ffDetectCodecNative(options, result);
|
||||
}
|
||||
@@ -37,3 +37,8 @@ typedef struct FFCodecResult {
|
||||
} FFCodecResult;
|
||||
|
||||
const char* ffDetectCodec(FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/);
|
||||
const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/);
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
const char* ffDetectCodecVulkan(FFlist* result /*list of FFCodecResult*/);
|
||||
#endif
|
||||
|
||||
@@ -54,7 +54,7 @@ static bool ffCodecIsHardwareAccelerated(
|
||||
return isHardware;
|
||||
}
|
||||
|
||||
const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/) {
|
||||
const char* ffDetectCodecNative(FF_A_UNUSED FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/) {
|
||||
FF_LIBRARY_LOAD_MESSAGE(mediandk, "libmediandk.so", 0)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mediandk, AMediaCodec_createDecoderByType)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mediandk, AMediaCodec_createEncoderByType)
|
||||
@@ -93,6 +93,6 @@ const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /*
|
||||
item->encoders = encoders;
|
||||
item->platformApi = "AMediaCodec";
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ static FFCodecType ffCodecDetectDecoders() {
|
||||
return types;
|
||||
}
|
||||
|
||||
const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
|
||||
const char* ffDetectCodecNative(FF_A_UNUSED FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
|
||||
FFCodecType decoders = ffCodecDetectDecoders();
|
||||
FFCodecType encoders = ffCodecDetectEncoders();
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
#include "common/library.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#if FF_CODEC_HAVE_VA
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <va/va.h>
|
||||
@@ -529,7 +529,7 @@ static const char* ffDetectCodecByVdpau(FFlist* result) {
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
|
||||
const char* ffDetectCodecNative(FF_A_UNUSED FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
|
||||
FF_SUPPRESS_IO();
|
||||
|
||||
#if FF_CODEC_HAVE_VA
|
||||
@@ -549,7 +549,7 @@ const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /*
|
||||
|
||||
#else
|
||||
|
||||
const char* ffDetectCodec(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
|
||||
const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
|
||||
FF_UNUSED(options, result);
|
||||
return "Fastfetch was built without DRM / VA-API / VDPAU headers";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
#include "codec.h"
|
||||
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
static FFCodecType ffCodecDecodeOperationsToTypes(VkVideoCodecOperationFlagsKHR operations) {
|
||||
FFCodecType types = FF_CODEC_TYPE_NONE;
|
||||
|
||||
if (operations & VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
|
||||
types |= FF_CODEC_TYPE_H264;
|
||||
}
|
||||
if (operations & VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
|
||||
types |= FF_CODEC_TYPE_HEVC;
|
||||
}
|
||||
if (operations & VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
|
||||
types |= FF_CODEC_TYPE_AV1;
|
||||
}
|
||||
if (operations & 0x00000008 /*VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR*/) {
|
||||
types |= FF_CODEC_TYPE_VP9;
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
static FFCodecType ffCodecEncodeOperationsToTypes(VkVideoCodecOperationFlagsKHR operations) {
|
||||
FFCodecType types = FF_CODEC_TYPE_NONE;
|
||||
|
||||
if (operations & VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR) {
|
||||
types |= FF_CODEC_TYPE_H264;
|
||||
}
|
||||
if (operations & VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) {
|
||||
types |= FF_CODEC_TYPE_HEVC;
|
||||
}
|
||||
if (operations & VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR) {
|
||||
types |= FF_CODEC_TYPE_AV1;
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
static bool ffCodecHasDeviceExtension(const VkExtensionProperties* extensions, uint32_t extensionCount, const char* extensionName) {
|
||||
for (uint32_t i = 0; i < extensionCount; ++i) {
|
||||
if (strcmp(extensions[i].extensionName, extensionName) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffDetectCodecVulkan(FFlist* result /*list of FFCodecResult*/) {
|
||||
FF_DEBUG("Starting Vulkan codec detection");
|
||||
|
||||
FF_LIBRARY_LOAD_MESSAGE(vulkan,
|
||||
#if __APPLE__
|
||||
"libMoltenVK" FF_LIBRARY_EXTENSION,
|
||||
-1
|
||||
#elif _WIN32
|
||||
"vulkan-1" FF_LIBRARY_EXTENSION,
|
||||
-1
|
||||
#else
|
||||
"libvulkan" FF_LIBRARY_EXTENSION,
|
||||
2
|
||||
#endif
|
||||
)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetInstanceProcAddr)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkCreateInstance)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkDestroyInstance)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkEnumeratePhysicalDevices)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkEnumerateDeviceExtensionProperties)
|
||||
|
||||
FF_SUPPRESS_IO();
|
||||
|
||||
uint32_t apiVersion = VK_API_VERSION_1_0;
|
||||
PFN_vkEnumerateInstanceVersion ffvkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion) ffvkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
|
||||
if (ffvkEnumerateInstanceVersion != NULL) {
|
||||
uint32_t detectedApiVersion = 0;
|
||||
if (ffvkEnumerateInstanceVersion(&detectedApiVersion) == VK_SUCCESS) {
|
||||
apiVersion = detectedApiVersion;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t projectVersion = VK_MAKE_VERSION(
|
||||
FASTFETCH_PROJECT_VERSION_MAJOR,
|
||||
FASTFETCH_PROJECT_VERSION_MINOR,
|
||||
FASTFETCH_PROJECT_VERSION_PATCH);
|
||||
|
||||
VkInstance vkInstance = VK_NULL_HANDLE;
|
||||
VkResult res = ffvkCreateInstance(&(VkInstanceCreateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pApplicationInfo = &(VkApplicationInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pApplicationName = FASTFETCH_PROJECT_NAME,
|
||||
.applicationVersion = projectVersion,
|
||||
.pEngineName = "fastfetch-codec-vulkan",
|
||||
.engineVersion = projectVersion,
|
||||
.apiVersion = apiVersion,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&vkInstance);
|
||||
if (res != VK_SUCCESS) {
|
||||
FF_DEBUG("ffvkCreateInstance() failed with VkResult=%d", res);
|
||||
switch (res) {
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||
return "ffvkCreateInstance() failed: VK_ERROR_OUT_OF_HOST_MEMORY";
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||
return "ffvkCreateInstance() failed: VK_ERROR_OUT_OF_DEVICE_MEMORY";
|
||||
case VK_ERROR_INITIALIZATION_FAILED:
|
||||
return "ffvkCreateInstance() failed: VK_ERROR_INITIALIZATION_FAILED";
|
||||
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||
return "ffvkCreateInstance() failed: VK_ERROR_LAYER_NOT_PRESENT";
|
||||
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
||||
return "ffvkCreateInstance() failed: VK_ERROR_EXTENSION_NOT_PRESENT";
|
||||
case VK_ERROR_INCOMPATIBLE_DRIVER:
|
||||
return "ffvkCreateInstance() failed: VK_ERROR_INCOMPATIBLE_DRIVER";
|
||||
default:
|
||||
return "ffvkCreateInstance() failed: unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
PFN_vkGetPhysicalDeviceProperties ffvkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties");
|
||||
if (!ffvkGetPhysicalDeviceProperties) {
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
return "vkGetPhysicalDeviceProperties is not available";
|
||||
}
|
||||
|
||||
PFN_vkGetPhysicalDeviceQueueFamilyProperties2 ffvkGetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceQueueFamilyProperties2");
|
||||
if (!ffvkGetPhysicalDeviceQueueFamilyProperties2) {
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
return "vkGetPhysicalDeviceQueueFamilyProperties2 is not available";
|
||||
}
|
||||
|
||||
uint32_t physicalDeviceCount = 0;
|
||||
res = ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, NULL);
|
||||
if (res != VK_SUCCESS) {
|
||||
FF_DEBUG("ffvkEnumeratePhysicalDevices(count) failed with VkResult=%d", res);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
return "ffvkEnumeratePhysicalDevices() failed during Vulkan codec detection";
|
||||
}
|
||||
if (physicalDeviceCount == 0) {
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
return "No Vulkan physical devices found";
|
||||
}
|
||||
|
||||
FF_AUTO_FREE VkPhysicalDevice* physicalDevices = (VkPhysicalDevice*) malloc(sizeof(VkPhysicalDevice) * (size_t) physicalDeviceCount);
|
||||
if (!physicalDevices) {
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
return "malloc() failed";
|
||||
}
|
||||
|
||||
res = ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices);
|
||||
if (res != VK_SUCCESS) {
|
||||
FF_DEBUG("ffvkEnumeratePhysicalDevices(list) failed with VkResult=%d", res);
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
return "ffvkEnumeratePhysicalDevices() failed during Vulkan codec detection";
|
||||
}
|
||||
|
||||
bool sawVideoQueueExtension = false;
|
||||
|
||||
for (uint32_t i = 0; i < physicalDeviceCount; ++i) {
|
||||
VkPhysicalDeviceProperties properties = {};
|
||||
ffvkGetPhysicalDeviceProperties(physicalDevices[i], &properties);
|
||||
|
||||
uint32_t extensionCount = 0;
|
||||
res = ffvkEnumerateDeviceExtensionProperties(physicalDevices[i], NULL, &extensionCount, NULL);
|
||||
if (res != VK_SUCCESS) {
|
||||
FF_DEBUG("vkEnumerateDeviceExtensionProperties(count) failed for '%s' with VkResult=%d", properties.deviceName, res);
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_FREE VkExtensionProperties* extensions = NULL;
|
||||
if (extensionCount > 0) {
|
||||
extensions = (VkExtensionProperties*) malloc(sizeof(VkExtensionProperties) * (size_t) extensionCount);
|
||||
if (!extensions) {
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
return "malloc() failed";
|
||||
}
|
||||
|
||||
res = ffvkEnumerateDeviceExtensionProperties(physicalDevices[i], NULL, &extensionCount, extensions);
|
||||
if (res != VK_SUCCESS) {
|
||||
FF_DEBUG("vkEnumerateDeviceExtensionProperties(list) failed for '%s' with VkResult=%d", properties.deviceName, res);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasVideoDecode = ffCodecHasDeviceExtension(extensions, extensionCount, VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
|
||||
bool hasVideoEncode = ffCodecHasDeviceExtension(extensions, extensionCount, VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME);
|
||||
|
||||
if (!hasVideoDecode && !hasVideoEncode) {
|
||||
FF_DEBUG("Skipping Vulkan device '%s' because it does not support video queue extensions", properties.deviceName);
|
||||
continue;
|
||||
}
|
||||
sawVideoQueueExtension = true;
|
||||
|
||||
uint32_t queueFamilyCount = 0;
|
||||
ffvkGetPhysicalDeviceQueueFamilyProperties2(physicalDevices[i], &queueFamilyCount, NULL);
|
||||
if (queueFamilyCount == 0) {
|
||||
FF_DEBUG("Skipping Vulkan device '%s' because it has no queue families", properties.deviceName);
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_FREE VkQueueFamilyProperties2* queueFamilyProperties = (VkQueueFamilyProperties2*) malloc(sizeof(VkQueueFamilyProperties2) * (size_t) queueFamilyCount);
|
||||
FF_AUTO_FREE VkQueueFamilyVideoPropertiesKHR* queueFamilyVideoProperties = (VkQueueFamilyVideoPropertiesKHR*) malloc(sizeof(VkQueueFamilyVideoPropertiesKHR) * (size_t) queueFamilyCount);
|
||||
if (!queueFamilyProperties || !queueFamilyVideoProperties) {
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
return "malloc() failed";
|
||||
}
|
||||
|
||||
for (uint32_t queueIndex = 0; queueIndex < queueFamilyCount; ++queueIndex) {
|
||||
queueFamilyVideoProperties[queueIndex] = (VkQueueFamilyVideoPropertiesKHR){
|
||||
.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
|
||||
};
|
||||
queueFamilyProperties[queueIndex] = (VkQueueFamilyProperties2){
|
||||
.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
|
||||
.pNext = &queueFamilyVideoProperties[queueIndex],
|
||||
};
|
||||
}
|
||||
|
||||
ffvkGetPhysicalDeviceQueueFamilyProperties2(physicalDevices[i], &queueFamilyCount, queueFamilyProperties);
|
||||
|
||||
FFCodecType decoders = FF_CODEC_TYPE_NONE;
|
||||
FFCodecType encoders = FF_CODEC_TYPE_NONE;
|
||||
|
||||
for (uint32_t queueIndex = 0; queueIndex < queueFamilyCount; ++queueIndex) {
|
||||
const VkQueueFlags queueFlags = queueFamilyProperties[queueIndex].queueFamilyProperties.queueFlags;
|
||||
const VkVideoCodecOperationFlagsKHR operations = queueFamilyVideoProperties[queueIndex].videoCodecOperations;
|
||||
|
||||
if (hasVideoDecode && (queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR)) {
|
||||
decoders |= ffCodecDecodeOperationsToTypes(operations);
|
||||
}
|
||||
|
||||
if (hasVideoEncode && (queueFlags & VK_QUEUE_VIDEO_ENCODE_BIT_KHR)) {
|
||||
encoders |= ffCodecEncodeOperationsToTypes(operations);
|
||||
}
|
||||
}
|
||||
|
||||
if (decoders == FF_CODEC_TYPE_NONE && encoders == FF_CODEC_TYPE_NONE) {
|
||||
FF_DEBUG("Skipping Vulkan device '%s' because no supported codec operations were reported", properties.deviceName);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFCodecResult* item = FF_LIST_ADD(FFCodecResult, *result);
|
||||
ffStrbufInitS(&item->gpu, properties.deviceName);
|
||||
item->decoders = decoders;
|
||||
item->encoders = encoders;
|
||||
item->platformApi = "vulkan_video";
|
||||
FF_DEBUG("Added Vulkan codec result for '%s': decoders=%u encoders=%u", properties.deviceName, (unsigned) decoders, (unsigned) encoders);
|
||||
}
|
||||
|
||||
ffvkDestroyInstance(vkInstance, NULL);
|
||||
|
||||
if (result->length > 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sawVideoQueueExtension ? "No supported Vulkan video codec operations found"
|
||||
: "VK_KHR_video_queue is not supported by any Vulkan physical device";
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -422,7 +422,7 @@ const char* detectD3d12va(FFlist* result /*list of FFCodecResult*/, IDXGIFactory
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* ffDetectCodec(FF_A_UNUSED FFCodecOptions* options, FFlist* result /*list of FFCodecResult*/) {
|
||||
const char* ffDetectCodecNative(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)
|
||||
|
||||
|
||||
@@ -154,6 +154,11 @@ void ffParseCodecJsonObject(FFCodecOptions* options, yyjson_val* module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "useVulkan")) {
|
||||
options->useVulkan = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
@@ -161,11 +166,12 @@ void ffParseCodecJsonObject(FFCodecOptions* options, yyjson_val* module) {
|
||||
void ffGenerateCodecJsonConfig(FFCodecOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
|
||||
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);
|
||||
}
|
||||
|
||||
bool ffGenerateCodecJsonResult(FF_A_UNUSED FFCodecOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
|
||||
bool ffGenerateCodecJsonResult(FFCodecOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
|
||||
FF_LIST_AUTO_DESTROY result = ffListCreate();
|
||||
const char* error = ffDetectCodec(NULL, &result);
|
||||
const char* error = ffDetectCodec(options, &result);
|
||||
|
||||
if (error) {
|
||||
yyjson_mut_obj_add_str(doc, module, "error", error);
|
||||
@@ -201,6 +207,7 @@ bool ffGenerateCodecJsonResult(FF_A_UNUSED FFCodecOptions* options, yyjson_mut_d
|
||||
void ffInitCodecOptions(FFCodecOptions* options) {
|
||||
ffOptionInitModuleArg(&options->moduleArgs, "");
|
||||
options->splitGPU = false;
|
||||
options->useVulkan = false;
|
||||
}
|
||||
|
||||
void ffDestroyCodecOptions(FFCodecOptions* options) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
typedef struct FFCodecOptions {
|
||||
FFModuleArgs moduleArgs;
|
||||
bool splitGPU;
|
||||
bool useVulkan;
|
||||
} FFCodecOptions;
|
||||
|
||||
static_assert(sizeof(FFCodecOptions) <= FF_OPTION_MAX_SIZE, "FFCodecOptions size exceeds maximum allowed size");
|
||||
|
||||
Reference in New Issue
Block a user