diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/command_classes/codecs/codec.cpp | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp index 916277811..02d309170 100644 --- a/src/video_core/command_classes/codecs/codec.cpp +++ b/src/video_core/command_classes/codecs/codec.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 6 | #include <cstdio> | ||
| 5 | #include <fstream> | 7 | #include <fstream> |
| 6 | #include <vector> | 8 | #include <vector> |
| 7 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| @@ -59,6 +61,34 @@ Codec::~Codec() { | |||
| 59 | av_buffer_unref(&av_gpu_decoder); | 61 | av_buffer_unref(&av_gpu_decoder); |
| 60 | } | 62 | } |
| 61 | 63 | ||
| 64 | #ifdef LIBVA_FOUND | ||
| 65 | // List all the currently loaded Linux modules | ||
| 66 | static std::vector<std::string> ListLinuxKernelModules() { | ||
| 67 | using FILEPtr = std::unique_ptr<FILE, decltype(&std::fclose)>; | ||
| 68 | auto module_listing = FILEPtr{fopen("/proc/modules", "rt"), std::fclose}; | ||
| 69 | std::vector<std::string> modules{}; | ||
| 70 | if (!module_listing) { | ||
| 71 | LOG_WARNING(Service_NVDRV, "Could not open /proc/modules to collect available modules"); | ||
| 72 | return modules; | ||
| 73 | } | ||
| 74 | char* buffer = nullptr; | ||
| 75 | size_t buf_len = 0; | ||
| 76 | while (getline(&buffer, &buf_len, module_listing.get()) != -1) { | ||
| 77 | // format for the module listing file (sysfs) | ||
| 78 | // <name> <module_size> <depended_by_count> <depended_by_names> <status> <load_address> | ||
| 79 | auto line = std::string(buffer); | ||
| 80 | // we are only interested in module names | ||
| 81 | auto name_pos = line.find_first_of(" "); | ||
| 82 | if (name_pos == std::string::npos) { | ||
| 83 | continue; | ||
| 84 | } | ||
| 85 | modules.push_back(line.erase(name_pos)); | ||
| 86 | } | ||
| 87 | free(buffer); | ||
| 88 | return modules; | ||
| 89 | } | ||
| 90 | #endif | ||
| 91 | |||
| 62 | bool Codec::CreateGpuAvDevice() { | 92 | bool Codec::CreateGpuAvDevice() { |
| 63 | #if defined(LIBVA_FOUND) | 93 | #if defined(LIBVA_FOUND) |
| 64 | static constexpr std::array<const char*, 3> VAAPI_DRIVERS = { | 94 | static constexpr std::array<const char*, 3> VAAPI_DRIVERS = { |
| @@ -67,8 +97,16 @@ bool Codec::CreateGpuAvDevice() { | |||
| 67 | "amdgpu", | 97 | "amdgpu", |
| 68 | }; | 98 | }; |
| 69 | AVDictionary* hwdevice_options = nullptr; | 99 | AVDictionary* hwdevice_options = nullptr; |
| 100 | const auto loaded_modules = ListLinuxKernelModules(); | ||
| 70 | av_dict_set(&hwdevice_options, "connection_type", "drm", 0); | 101 | av_dict_set(&hwdevice_options, "connection_type", "drm", 0); |
| 71 | for (const auto& driver : VAAPI_DRIVERS) { | 102 | for (const auto& driver : VAAPI_DRIVERS) { |
| 103 | // first check if the target driver is loaded in the kernel | ||
| 104 | bool found = std::any_of(loaded_modules.begin(), loaded_modules.end(), | ||
| 105 | [&driver](const auto& module) { return module == driver; }); | ||
| 106 | if (!found) { | ||
| 107 | LOG_DEBUG(Service_NVDRV, "Kernel driver {} is not loaded, trying the next one", driver); | ||
| 108 | continue; | ||
| 109 | } | ||
| 72 | av_dict_set(&hwdevice_options, "kernel_driver", driver, 0); | 110 | av_dict_set(&hwdevice_options, "kernel_driver", driver, 0); |
| 73 | const int hwdevice_error = av_hwdevice_ctx_create(&av_gpu_decoder, AV_HWDEVICE_TYPE_VAAPI, | 111 | const int hwdevice_error = av_hwdevice_ctx_create(&av_gpu_decoder, AV_HWDEVICE_TYPE_VAAPI, |
| 74 | nullptr, hwdevice_options, 0); | 112 | nullptr, hwdevice_options, 0); |
| @@ -85,11 +123,12 @@ bool Codec::CreateGpuAvDevice() { | |||
| 85 | #endif | 123 | #endif |
| 86 | static constexpr auto HW_CONFIG_METHOD = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX; | 124 | static constexpr auto HW_CONFIG_METHOD = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX; |
| 87 | static constexpr std::array GPU_DECODER_TYPES{ | 125 | static constexpr std::array GPU_DECODER_TYPES{ |
| 126 | #ifdef linux | ||
| 127 | AV_HWDEVICE_TYPE_VDPAU, | ||
| 128 | #endif | ||
| 88 | AV_HWDEVICE_TYPE_CUDA, | 129 | AV_HWDEVICE_TYPE_CUDA, |
| 89 | #ifdef _WIN32 | 130 | #ifdef _WIN32 |
| 90 | AV_HWDEVICE_TYPE_D3D11VA, | 131 | AV_HWDEVICE_TYPE_D3D11VA, |
| 91 | #else | ||
| 92 | AV_HWDEVICE_TYPE_VDPAU, | ||
| 93 | #endif | 132 | #endif |
| 94 | }; | 133 | }; |
| 95 | for (const auto& type : GPU_DECODER_TYPES) { | 134 | for (const auto& type : GPU_DECODER_TYPES) { |