common_utils_windows.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "common_utils.h"
  2. // ATTENTION: If D3D surfaces are used, DX9_D3D or DX11_D3D must be set in project settings or hardcoded here
  3. #ifdef DX9_D3D
  4. #include "common_directx.h"
  5. #elif DX11_D3D
  6. #include "common_directx11.h"
  7. #include "common_directx9.h"
  8. #endif
  9. #include <util/windows/device-enum.h>
  10. #include <util/config-file.h>
  11. #include <util/platform.h>
  12. #include <util/pipe.h>
  13. #include <util/dstr.h>
  14. #include <intrin.h>
  15. #include <inttypes.h>
  16. /* =======================================================
  17. * Windows implementation of OS-specific utility functions
  18. */
  19. mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession *pSession,
  20. mfxFrameAllocator *pmfxAllocator, mfxHDL *deviceHandle,
  21. bool bCreateSharedHandles, bool dx9hack)
  22. {
  23. bCreateSharedHandles; // (Lain) Currently unused
  24. pmfxAllocator; // (Lain) Currently unused
  25. mfxStatus sts = MFX_ERR_NONE;
  26. // If mfxFrameAllocator is provided it means we need to setup DirectX device and memory allocator
  27. if (pmfxAllocator && !dx9hack) {
  28. // Initialize Intel Media SDK Session
  29. sts = pSession->Init(impl, &ver);
  30. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  31. // Create DirectX device context
  32. if (deviceHandle == NULL || *deviceHandle == NULL) {
  33. sts = CreateHWDevice(*pSession, deviceHandle, NULL,
  34. bCreateSharedHandles);
  35. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  36. }
  37. if (deviceHandle == NULL || *deviceHandle == NULL)
  38. return MFX_ERR_DEVICE_FAILED;
  39. // Provide device manager to Media SDK
  40. sts = pSession->SetHandle(DEVICE_MGR_TYPE, *deviceHandle);
  41. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  42. pmfxAllocator->pthis =
  43. *pSession; // We use Media SDK session ID as the allocation identifier
  44. pmfxAllocator->Alloc = simple_alloc;
  45. pmfxAllocator->Free = simple_free;
  46. pmfxAllocator->Lock = simple_lock;
  47. pmfxAllocator->Unlock = simple_unlock;
  48. pmfxAllocator->GetHDL = simple_gethdl;
  49. // Since we are using video memory we must provide Media SDK with an external allocator
  50. sts = pSession->SetFrameAllocator(pmfxAllocator);
  51. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  52. } else if (pmfxAllocator && dx9hack) {
  53. // Initialize Intel Media SDK Session
  54. sts = pSession->Init(impl, &ver);
  55. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  56. // Create DirectX device context
  57. if (deviceHandle == NULL || *deviceHandle == NULL) {
  58. sts = DX9_CreateHWDevice(*pSession, deviceHandle, NULL,
  59. false);
  60. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  61. }
  62. if (*deviceHandle == NULL)
  63. return MFX_ERR_DEVICE_FAILED;
  64. // Provide device manager to Media SDK
  65. sts = pSession->SetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER,
  66. *deviceHandle);
  67. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  68. pmfxAllocator->pthis =
  69. *pSession; // We use Media SDK session ID as the allocation identifier
  70. pmfxAllocator->Alloc = dx9_simple_alloc;
  71. pmfxAllocator->Free = dx9_simple_free;
  72. pmfxAllocator->Lock = dx9_simple_lock;
  73. pmfxAllocator->Unlock = dx9_simple_unlock;
  74. pmfxAllocator->GetHDL = dx9_simple_gethdl;
  75. // Since we are using video memory we must provide Media SDK with an external allocator
  76. sts = pSession->SetFrameAllocator(pmfxAllocator);
  77. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  78. } else {
  79. // Initialize Intel Media SDK Session
  80. sts = pSession->Init(impl, &ver);
  81. MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts);
  82. }
  83. return sts;
  84. }
  85. void Release()
  86. {
  87. #if defined(DX9_D3D) || defined(DX11_D3D)
  88. CleanupHWDevice();
  89. DX9_CleanupHWDevice();
  90. #endif
  91. }
  92. void mfxGetTime(mfxTime *timestamp)
  93. {
  94. QueryPerformanceCounter(timestamp);
  95. }
  96. double TimeDiffMsec(mfxTime tfinish, mfxTime tstart)
  97. {
  98. static LARGE_INTEGER tFreq = {0};
  99. if (!tFreq.QuadPart)
  100. QueryPerformanceFrequency(&tFreq);
  101. double freq = (double)tFreq.QuadPart;
  102. return 1000.0 * ((double)tfinish.QuadPart - (double)tstart.QuadPart) /
  103. freq;
  104. }
  105. void util_cpuid(int cpuinfo[4], int flags)
  106. {
  107. return __cpuid(cpuinfo, flags);
  108. }
  109. static bool enum_luids(void *param, uint32_t idx, uint64_t luid)
  110. {
  111. struct dstr *cmd = (struct dstr *)param;
  112. dstr_catf(cmd, " %" PRIx64, luid);
  113. UNUSED_PARAMETER(idx);
  114. return true;
  115. }
  116. void check_adapters(struct adapter_info *adapters, size_t *adapter_count)
  117. {
  118. char *test_exe = os_get_executable_path_ptr("obs-qsv-test.exe");
  119. struct dstr cmd = {0};
  120. struct dstr caps_str = {0};
  121. os_process_pipe_t *pp = nullptr;
  122. config_t *config = nullptr;
  123. const char *error = nullptr;
  124. size_t config_adapter_count;
  125. dstr_copy(&cmd, test_exe);
  126. enum_graphics_device_luids(enum_luids, &cmd);
  127. pp = os_process_pipe_create(cmd.array, "r");
  128. if (!pp) {
  129. blog(LOG_INFO, "Failed to launch the QSV test process I guess");
  130. goto fail;
  131. }
  132. for (;;) {
  133. char data[2048];
  134. size_t len =
  135. os_process_pipe_read(pp, (uint8_t *)data, sizeof(data));
  136. if (!len)
  137. break;
  138. dstr_ncat(&caps_str, data, len);
  139. }
  140. if (dstr_is_empty(&caps_str)) {
  141. blog(LOG_INFO, "Seems the QSV test subprocess crashed. "
  142. "Better there than here I guess. "
  143. "Let's just skip loading QSV then I suppose.");
  144. goto fail;
  145. }
  146. if (config_open_string(&config, caps_str.array) != 0) {
  147. blog(LOG_INFO, "Couldn't open QSV configuration string");
  148. goto fail;
  149. }
  150. error = config_get_string(config, "error", "string");
  151. if (error) {
  152. blog(LOG_INFO, "Error querying QSV support: %s", error);
  153. goto fail;
  154. }
  155. config_adapter_count = config_num_sections(config);
  156. if (config_adapter_count < *adapter_count)
  157. *adapter_count = config_adapter_count;
  158. for (size_t i = 0; i < *adapter_count; i++) {
  159. char section[16];
  160. snprintf(section, sizeof(section), "%d", (int)i);
  161. struct adapter_info *adapter = &adapters[i];
  162. adapter->is_intel =
  163. config_get_bool(config, section, "is_intel");
  164. adapter->is_dgpu = config_get_bool(config, section, "is_dgpu");
  165. adapter->supports_av1 =
  166. config_get_bool(config, section, "supports_av1");
  167. adapter->supports_hevc =
  168. config_get_bool(config, section, "supports_hevc");
  169. }
  170. fail:
  171. config_close(config);
  172. dstr_free(&caps_str);
  173. dstr_free(&cmd);
  174. os_process_pipe_destroy(pp);
  175. bfree(test_exe);
  176. }
  177. /* (Lain) Functions currently unused */
  178. #if 0
  179. void ClearYUVSurfaceVMem(mfxMemId memId)
  180. {
  181. #if defined(DX9_D3D) || defined(DX11_D3D)
  182. ClearYUVSurfaceD3D(memId);
  183. #endif
  184. }
  185. void ClearRGBSurfaceVMem(mfxMemId memId)
  186. {
  187. #if defined(DX9_D3D) || defined(DX11_D3D)
  188. ClearRGBSurfaceD3D(memId);
  189. #endif
  190. }
  191. #endif