summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/command_classes/codecs/codec.cpp43
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
66static 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
62bool Codec::CreateGpuAvDevice() { 92bool 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) {