Advertisement
Guest User

amfpatch

a guest
Feb 5th, 2023
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.89 KB | None | 0 0
  1. --- a/plugins/obs-ffmpeg/CMakeLists.txt
  2. +++ b/plugins/obs-ffmpeg/CMakeLists.txt
  3. @@ -119,11 +119,14 @@
  4. obs-ffmpeg.rc)
  5.  
  6. elseif(OS_POSIX AND NOT OS_MACOS)
  7. + add_subdirectory(obs-amf-test)
  8. find_package(Libva REQUIRED)
  9. find_package(Libpci REQUIRED)
  10. target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c
  11. vaapi-utils.h)
  12. target_link_libraries(obs-ffmpeg PRIVATE Libva::va LIBPCI::LIBPCI)
  13. + target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c texture-amf.cpp)
  14. + target_link_libraries(obs-ffmpeg PRIVATE LIBPCI::LIBPCI)
  15. endif()
  16.  
  17. setup_plugin_target(obs-ffmpeg)
  18. --- a/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt
  19. +++ b/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt
  20. @@ -3,8 +3,15 @@
  21. include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/libobs)
  22.  
  23. add_executable(obs-amf-test)
  24. -target_sources(obs-amf-test PRIVATE obs-amf-test.cpp)
  25. -target_link_libraries(obs-amf-test d3d11 dxgi dxguid)
  26. +
  27. +if(OS_WINDOWS)
  28. + target_sources(obs-amf-test PRIVATE obs-amf-test.cpp)
  29. + target_link_libraries(obs-amf-test d3d11 dxgi dxguid)
  30. +elseif(OS_POSIX AND NOT OS_MACOS)
  31. + find_package(Vulkan REQUIRED)
  32. + target_sources(obs-amf-test PRIVATE obs-amf-test-linux.cpp)
  33. + target_link_libraries(obs-amf-test dl Vulkan::Vulkan)
  34. +endif()
  35.  
  36. set_target_properties(obs-amf-test PROPERTIES FOLDER "plugins/obs-ffmpeg")
  37.  
  38. --- /dev/null
  39. +++ b/plugins/obs-ffmpeg/obs-amf-test/obs-amf-test-linux.cpp
  40. @@ -0,0 +1,140 @@
  41. +#include "../external/AMF/include/core/Factory.h"
  42. +#include "../external/AMF/include/core/Trace.h"
  43. +#include "../external/AMF/include/components/VideoEncoderVCE.h"
  44. +#include "../external/AMF/include/components/VideoEncoderHEVC.h"
  45. +#include "../external/AMF/include/components/VideoEncoderAV1.h"
  46. +
  47. +#include <dlfcn.h>
  48. +#include <vulkan/vulkan.hpp>
  49. +
  50. +#include <string>
  51. +#include <map>
  52. +
  53. +using namespace amf;
  54. +
  55. +struct adapter_caps {
  56. + bool is_amd = false;
  57. + bool supports_avc = false;
  58. + bool supports_hevc = false;
  59. + bool supports_av1 = false;
  60. +};
  61. +
  62. +static AMFFactory *amf_factory = nullptr;
  63. +static std::map<uint32_t, adapter_caps> adapter_info;
  64. +
  65. +static bool has_encoder(AMFContextPtr &amf_context, const wchar_t *encoder_name)
  66. +{
  67. + AMFComponentPtr encoder;
  68. + AMF_RESULT res = amf_factory->CreateComponent(amf_context, encoder_name,
  69. + &encoder);
  70. + return res == AMF_OK;
  71. +}
  72. +
  73. +static bool get_adapter_caps(uint32_t adapter_idx)
  74. +{
  75. + if (adapter_idx)
  76. + return false;
  77. +
  78. + adapter_caps &caps = adapter_info[adapter_idx];
  79. +
  80. + AMF_RESULT res;
  81. + AMFContextPtr amf_context;
  82. + res = amf_factory->CreateContext(&amf_context);
  83. + if (res != AMF_OK)
  84. + return true;
  85. +
  86. + AMFContext1 *context1 = NULL;
  87. + res = amf_context->QueryInterface(AMFContext1::IID(),
  88. + (void **)&context1);
  89. + if (res != AMF_OK)
  90. + return false;
  91. + res = context1->InitVulkan(nullptr);
  92. + context1->Release();
  93. + if (res != AMF_OK)
  94. + return false;
  95. +
  96. + caps.is_amd = true;
  97. + caps.supports_avc = has_encoder(amf_context, AMFVideoEncoderVCE_AVC);
  98. + caps.supports_hevc = has_encoder(amf_context, AMFVideoEncoder_HEVC);
  99. + caps.supports_av1 = has_encoder(amf_context, AMFVideoEncoder_AV1);
  100. +
  101. + return true;
  102. +}
  103. +
  104. +int main(void)
  105. +try {
  106. + AMF_RESULT res;
  107. + VkResult vkres;
  108. +
  109. + VkApplicationInfo app_info = {};
  110. + app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  111. + app_info.pApplicationName = "obs-amf-test";
  112. + app_info.apiVersion = VK_API_VERSION_1_2;
  113. +
  114. + VkInstanceCreateInfo info = {};
  115. + info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  116. + info.pApplicationInfo = &app_info;
  117. +
  118. + VkInstance instance;
  119. + vkres = vkCreateInstance(&info, nullptr, &instance);
  120. + if (vkres != VK_SUCCESS)
  121. + throw "Failed to initialize Vulkan";
  122. +
  123. + uint32_t device_count;
  124. + vkres = vkEnumeratePhysicalDevices(instance, &device_count, nullptr);
  125. + if (vkres != VK_SUCCESS || !device_count)
  126. + throw "Failed to enumerate Vulkan devices";
  127. +
  128. + VkPhysicalDevice *devices = new VkPhysicalDevice[device_count];
  129. + vkres = vkEnumeratePhysicalDevices(instance, &device_count, devices);
  130. + if (vkres != VK_SUCCESS)
  131. + throw "Failed to enumerate Vulkan devices";
  132. +
  133. + VkPhysicalDeviceDriverProperties driver_props = {};
  134. + driver_props.sType =
  135. + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
  136. + VkPhysicalDeviceProperties2 device_props = {};
  137. + device_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
  138. + device_props.pNext = &driver_props;
  139. + vkGetPhysicalDeviceProperties2(devices[0], &device_props);
  140. +
  141. + if (strcmp(driver_props.driverName, "AMD proprietary driver"))
  142. + throw "Not running AMD proprietary driver";
  143. +
  144. + vkDestroyInstance(instance, nullptr);
  145. +
  146. + /* --------------------------------------------------------- */
  147. + /* try initializing amf, I guess */
  148. +
  149. + void *amf_module = dlopen(AMF_DLL_NAMEA, RTLD_LAZY);
  150. + if (!amf_module)
  151. + throw "Failed to load AMF lib";
  152. +
  153. + auto init = (AMFInit_Fn)dlsym(amf_module, AMF_INIT_FUNCTION_NAME);
  154. + if (!init)
  155. + throw "Failed to get init func";
  156. +
  157. + res = init(AMF_FULL_VERSION, &amf_factory);
  158. + if (res != AMF_OK)
  159. + throw "AMFInit failed";
  160. +
  161. + uint32_t idx = 0;
  162. + while (get_adapter_caps(idx++))
  163. + ;
  164. +
  165. + for (auto &[idx, caps] : adapter_info) {
  166. + printf("[%u]\n", idx);
  167. + printf("is_amd=%s\n", caps.is_amd ? "true" : "false");
  168. + printf("supports_avc=%s\n",
  169. + caps.supports_avc ? "true" : "false");
  170. + printf("supports_hevc=%s\n",
  171. + caps.supports_hevc ? "true" : "false");
  172. + printf("supports_av1=%s\n",
  173. + caps.supports_av1 ? "true" : "false");
  174. + }
  175. +
  176. + return 0;
  177. +} catch (const char *text) {
  178. + printf("[error]\nstring=%s\n", text);
  179. + return 0;
  180. +}
  181. --- a/plugins/obs-ffmpeg/obs-ffmpeg.c
  182. +++ b/plugins/obs-ffmpeg/obs-ffmpeg.c
  183. @@ -339,6 +339,9 @@
  184. #ifdef _WIN32
  185. extern void jim_nvenc_load(bool h264, bool hevc, bool av1);
  186. extern void jim_nvenc_unload(void);
  187. +#endif
  188. +
  189. +#if defined(_WIN32) || defined(__linux__)
  190. extern void amf_load(void);
  191. extern void amf_unload(void);
  192. #endif
  193. @@ -408,7 +411,7 @@
  194. #endif
  195. }
  196.  
  197. -#ifdef _WIN32
  198. +#if defined(_WIN32) || defined(__linux__)
  199. amf_load();
  200. #endif
  201.  
  202. @@ -440,8 +443,11 @@
  203. obs_ffmpeg_unload_logging();
  204. #endif
  205.  
  206. -#ifdef _WIN32
  207. +#if defined(_WIN32) || defined(__linux__)
  208. amf_unload();
  209. +#endif
  210. +
  211. +#ifdef _WIN32
  212. jim_nvenc_unload();
  213. #endif
  214. }
  215. --- a/plugins/obs-ffmpeg/texture-amf-opts.hpp
  216. +++ b/plugins/obs-ffmpeg/texture-amf-opts.hpp
  217. @@ -321,7 +321,7 @@
  218. val = atoi(opt->value);
  219. }
  220.  
  221. - os_utf8_to_wcs(opt->name, 0, wname, _countof(wname));
  222. + os_utf8_to_wcs(opt->name, 0, wname, amf_countof(wname));
  223. if (is_bool) {
  224. bool bool_val = (bool)val;
  225. set_amf_property(enc, wname, bool_val);
  226. --- a/plugins/obs-ffmpeg/texture-amf.cpp
  227. +++ b/plugins/obs-ffmpeg/texture-amf.cpp
  228. @@ -20,6 +20,7 @@
  229. #include "external/AMF/include/core/Factory.h"
  230. #include "external/AMF/include/core/Trace.h"
  231.  
  232. +#ifdef _WIN32
  233. #include <dxgi.h>
  234. #include <d3d11.h>
  235. #include <d3d11_1.h>
  236. @@ -27,6 +28,8 @@
  237. #include <util/windows/device-enum.h>
  238. #include <util/windows/HRError.hpp>
  239. #include <util/windows/ComPtr.hpp>
  240. +#endif
  241. +
  242. #include <util/platform.h>
  243. #include <util/util.hpp>
  244. #include <util/pipe.h>
  245. @@ -57,8 +60,10 @@
  246.  
  247. struct handle_tex {
  248. uint32_t handle;
  249. +#ifdef _WIN32
  250. ComPtr<ID3D11Texture2D> tex;
  251. ComPtr<IDXGIKeyedMutex> km;
  252. +#endif
  253. };
  254.  
  255. struct adapter_caps {
  256. @@ -74,7 +79,7 @@
  257. static bool h264_supported = false;
  258. static AMFFactory *amf_factory = nullptr;
  259. static AMFTrace *amf_trace = nullptr;
  260. -static HMODULE amf_module = nullptr;
  261. +static void *amf_module = nullptr;
  262. static uint64_t amf_version = 0;
  263.  
  264. /* ========================================================================= */
  265. @@ -122,9 +127,11 @@
  266. virtual void init() = 0;
  267. };
  268.  
  269. -using d3dtex_t = ComPtr<ID3D11Texture2D>;
  270. using buf_t = std::vector<uint8_t>;
  271.  
  272. +#ifdef _WIN32
  273. +using d3dtex_t = ComPtr<ID3D11Texture2D>;
  274. +
  275. struct amf_texencode : amf_base, public AMFSurfaceObserver {
  276. volatile bool destroying = false;
  277.  
  278. @@ -161,6 +168,7 @@
  279. throw amf_error("InitDX11 failed", res);
  280. }
  281. };
  282. +#endif
  283.  
  284. struct amf_fallback : amf_base, public AMFSurfaceObserver {
  285. volatile bool destroying = false;
  286. @@ -188,9 +196,21 @@
  287.  
  288. void init() override
  289. {
  290. +#if defined(_WIN32)
  291. AMF_RESULT res = amf_context->InitDX11(nullptr, AMF_DX11_1);
  292. if (res != AMF_OK)
  293. throw amf_error("InitDX11 failed", res);
  294. +#elif defined(__linux__)
  295. + AMFContext1 *context1 = NULL;
  296. + AMF_RESULT res = amf_context->QueryInterface(
  297. + AMFContext1::IID(), (void **)&context1);
  298. + if (res != AMF_OK)
  299. + throw amf_error("CreateContext1 failed", res);
  300. + res = context1->InitVulkan(nullptr);
  301. + context1->Release();
  302. + if (res != AMF_OK)
  303. + throw amf_error("InitVulkan failed", res);
  304. +#endif
  305. }
  306. };
  307.  
  308. @@ -249,6 +269,7 @@
  309. /* ------------------------------------------------------------------------- */
  310. /* Implementation */
  311.  
  312. +#ifdef _WIN32
  313. static HMODULE get_lib(const char *lib)
  314. {
  315. HMODULE mod = GetModuleHandleA(lib);
  316. @@ -395,6 +416,7 @@
  317. *km_out = km.Detach();
  318. *tex_out = tex.Detach();
  319. }
  320. +#endif
  321.  
  322. static constexpr amf_int64 macroblock_size = 16;
  323.  
  324. @@ -640,6 +662,7 @@
  325. static bool amf_encode_tex(void *data, uint32_t handle, int64_t pts,
  326. uint64_t lock_key, uint64_t *next_key,
  327. encoder_packet *packet, bool *received_packet)
  328. +#ifdef _WIN32
  329. try {
  330. amf_texencode *enc = (amf_texencode *)data;
  331. ID3D11DeviceContext *context = enc->context;
  332. @@ -716,6 +739,18 @@
  333. *received_packet = false;
  334. return false;
  335. }
  336. +#else
  337. +{
  338. + UNUSED_PARAMETER(data);
  339. + UNUSED_PARAMETER(handle);
  340. + UNUSED_PARAMETER(pts);
  341. + UNUSED_PARAMETER(lock_key);
  342. + UNUSED_PARAMETER(next_key);
  343. + UNUSED_PARAMETER(packet);
  344. + UNUSED_PARAMETER(received_packet);
  345. + return false;
  346. +}
  347. +#endif
  348.  
  349. static buf_t alloc_buf(amf_fallback *enc)
  350. {
  351. @@ -1406,6 +1441,7 @@
  352.  
  353. static void *amf_avc_create_texencode(obs_data_t *settings,
  354. obs_encoder_t *encoder)
  355. +#ifdef _WIN32
  356. try {
  357. check_texture_encode_capability(encoder, amf_codec_type::AVC);
  358.  
  359. @@ -1428,6 +1464,12 @@
  360. blog(LOG_ERROR, "[texture-amf-h264] %s: %s", __FUNCTION__, err);
  361. return obs_encoder_create_rerouted(encoder, "h264_fallback_amf");
  362. }
  363. +#else
  364. +{
  365. + UNUSED_PARAMETER(settings);
  366. + return obs_encoder_create_rerouted(encoder, "h264_fallback_amf");
  367. +}
  368. +#endif
  369.  
  370. static void *amf_avc_create_fallback(obs_data_t *settings,
  371. obs_encoder_t *encoder)
  372. @@ -1748,6 +1790,7 @@
  373.  
  374. static void *amf_hevc_create_texencode(obs_data_t *settings,
  375. obs_encoder_t *encoder)
  376. +#ifdef _WIN32
  377. try {
  378. check_texture_encode_capability(encoder, amf_codec_type::HEVC);
  379.  
  380. @@ -1770,6 +1813,12 @@
  381. blog(LOG_ERROR, "[texture-amf-h265] %s: %s", __FUNCTION__, err);
  382. return obs_encoder_create_rerouted(encoder, "h265_fallback_amf");
  383. }
  384. +#else
  385. +{
  386. + UNUSED_PARAMETER(settings);
  387. + return obs_encoder_create_rerouted(encoder, "h265_fallback_amf");
  388. +}
  389. +#endif
  390.  
  391. static void *amf_hevc_create_fallback(obs_data_t *settings,
  392. obs_encoder_t *encoder)
  393. @@ -2047,6 +2096,7 @@
  394.  
  395. static void *amf_av1_create_texencode(obs_data_t *settings,
  396. obs_encoder_t *encoder)
  397. +#ifdef _WIN32
  398. try {
  399. check_texture_encode_capability(encoder, amf_codec_type::AV1);
  400.  
  401. @@ -2069,6 +2119,12 @@
  402. blog(LOG_ERROR, "[texture-amf-av1] %s: %s", __FUNCTION__, err);
  403. return obs_encoder_create_rerouted(encoder, "av1_fallback_amf");
  404. }
  405. +#else
  406. +{
  407. + UNUSED_PARAMETER(settings);
  408. + return obs_encoder_create_rerouted(encoder, "av1_fallback_amf");
  409. +}
  410. +#endif
  411.  
  412. static void *amf_av1_create_fallback(obs_data_t *settings,
  413. obs_encoder_t *encoder)
  414. @@ -2151,17 +2207,16 @@
  415. /* ========================================================================= */
  416. /* Global Stuff */
  417.  
  418. -static bool enum_luids(void *param, uint32_t idx, uint64_t luid)
  419. -{
  420. - std::stringstream &cmd = *(std::stringstream *)param;
  421. - cmd << " " << std::hex << luid;
  422. - UNUSED_PARAMETER(idx);
  423. - return true;
  424. -}
  425. +#ifdef _WIN32
  426. +#define OBS_AMF_TEST "obs-amf-test.exe"
  427. +#else
  428. +#define OBS_AMF_TEST "obs-amf-test"
  429. +#endif
  430.  
  431. extern "C" void amf_load(void)
  432. try {
  433. AMF_RESULT res;
  434. +#ifdef _WIN32
  435. HMODULE amf_module_test;
  436.  
  437. /* Check if the DLL is present before running the more expensive */
  438. @@ -2171,18 +2226,20 @@
  439. if (!amf_module_test)
  440. throw "No AMF library";
  441. FreeLibrary(amf_module_test);
  442. +#else
  443. + void *amf_module_test = os_dlopen(AMF_DLL_NAMEA);
  444. + if (!amf_module_test)
  445. + throw "No AMF library";
  446. + os_dlclose(amf_module_test);
  447. +#endif
  448.  
  449. /* ----------------------------------- */
  450. /* Check for supported codecs */
  451.  
  452. - BPtr<char> test_exe = os_get_executable_path_ptr("obs-amf-test.exe");
  453. - std::stringstream cmd;
  454. + BPtr<char> test_exe = os_get_executable_path_ptr(OBS_AMF_TEST);
  455. std::string caps_str;
  456.  
  457. - cmd << test_exe;
  458. - enum_graphics_device_luids(enum_luids, &cmd);
  459. -
  460. - os_process_pipe_t *pp = os_process_pipe_create(cmd.str().c_str(), "r");
  461. + os_process_pipe_t *pp = os_process_pipe_create(test_exe, "r");
  462. if (!pp)
  463. throw "Failed to launch the AMF test process I guess";
  464.  
  465. @@ -2240,12 +2297,12 @@
  466. /* ----------------------------------- */
  467. /* Init AMF */
  468.  
  469. - amf_module = LoadLibraryW(AMF_DLL_NAME);
  470. + amf_module = os_dlopen(AMF_DLL_NAMEA);
  471. if (!amf_module)
  472. throw "AMF library failed to load";
  473.  
  474. AMFInit_Fn init =
  475. - (AMFInit_Fn)GetProcAddress(amf_module, AMF_INIT_FUNCTION_NAME);
  476. + (AMFInit_Fn)os_dlsym(amf_module, AMF_INIT_FUNCTION_NAME);
  477. if (!init)
  478. throw "Failed to get AMFInit address";
  479.  
  480. @@ -2257,7 +2314,7 @@
  481. if (res != AMF_OK)
  482. throw amf_error("GetTrace failed", res);
  483.  
  484. - AMFQueryVersion_Fn get_ver = (AMFQueryVersion_Fn)GetProcAddress(
  485. + AMFQueryVersion_Fn get_ver = (AMFQueryVersion_Fn)os_dlsym(
  486. amf_module, AMF_QUERY_VERSION_FUNCTION_NAME);
  487. if (!get_ver)
  488. throw "Failed to get AMFQueryVersion address";
  489.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement