/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp

https://github.com/arnova/xbmc · C++ · 1544 lines · 1224 code · 236 blank · 84 comment · 233 complexity · f48aa5f9e8315a00b2f42996b5b5961e MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * Copyright (C) 2005-2018 Team Kodi
  3. * This file is part of Kodi - https://kodi.tv
  4. *
  5. * SPDX-License-Identifier: GPL-2.0-or-later
  6. * See LICENSES/README.md for more information.
  7. */
  8. // setting that here because otherwise SampleFormat is defined to AVSampleFormat
  9. // which we don't use here
  10. #define FF_API_OLD_SAMPLE_FMT 0
  11. #define LIMIT_VIDEO_MEMORY_4K 2960ull
  12. #include "DXVA.h"
  13. #include "ServiceBroker.h"
  14. #include "cores/VideoPlayer/DVDCodecs/DVDCodecUtils.h"
  15. #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
  16. #include "cores/VideoPlayer/Process/ProcessInfo.h"
  17. #include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
  18. #include "rendering/dx/DeviceResources.h"
  19. #include "rendering/dx/RenderContext.h"
  20. #include "settings/AdvancedSettings.h"
  21. #include "settings/Settings.h"
  22. #include "settings/SettingsComponent.h"
  23. #include "utils/CPUInfo.h"
  24. #include "utils/StringUtils.h"
  25. #include "utils/SystemInfo.h"
  26. #include "utils/log.h"
  27. #include <Windows.h>
  28. #include <d3d11_4.h>
  29. #include <dxva.h>
  30. #include <initguid.h>
  31. using namespace DXVA;
  32. using namespace Microsoft::WRL;
  33. using namespace std::chrono_literals;
  34. DEFINE_GUID(DXVADDI_Intel_ModeH264_A, 0x604F8E64,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
  35. DEFINE_GUID(DXVADDI_Intel_ModeH264_C, 0x604F8E66,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
  36. DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
  37. DEFINE_GUID(DXVADDI_Intel_ModeVC1_E, 0xBCC5DB6D,0xA2B6,0x4AF0,0xAC,0xE4,0xAD,0xB1,0xF7,0x87,0xBC,0x89);
  38. DEFINE_GUID(DXVA_ModeH264_VLD_NoFGT_Flash, 0x4245F676,0x2BBC,0x4166,0xa0,0xBB,0x54,0xE7,0xB8,0x49,0xC3,0x80);
  39. DEFINE_GUID(DXVA_Intel_VC1_ClearVideo_2, 0xE07EC519,0xE651,0x4CD6,0xAC,0x84,0x13,0x70,0xCC,0xEE,0xC8,0x51);
  40. // redefine DXVA_NoEncrypt with other macro, solves unresolved external symbol linker error
  41. #ifndef DXVA_NoEncrypt
  42. DEFINE_GUID(DXVA_NoEncrypt, 0x1b81beD0, 0xa0c7, 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5);
  43. #endif
  44. static const int PROFILES_MPEG2_SIMPLE[] = { FF_PROFILE_MPEG2_SIMPLE,
  45. FF_PROFILE_UNKNOWN };
  46. static const int PROFILES_MPEG2_MAIN[] = { FF_PROFILE_MPEG2_SIMPLE,
  47. FF_PROFILE_MPEG2_MAIN,
  48. FF_PROFILE_UNKNOWN };
  49. static const int PROFILES_H264_HIGH[] = { FF_PROFILE_H264_BASELINE,
  50. FF_PROFILE_H264_CONSTRAINED_BASELINE,
  51. FF_PROFILE_H264_MAIN,
  52. FF_PROFILE_H264_HIGH,
  53. FF_PROFILE_UNKNOWN };
  54. static const int PROFILES_HEVC_MAIN[] = { FF_PROFILE_HEVC_MAIN,
  55. FF_PROFILE_UNKNOWN };
  56. static const int PROFILES_HEVC_MAIN10[] = { FF_PROFILE_HEVC_MAIN,
  57. FF_PROFILE_HEVC_MAIN_10,
  58. FF_PROFILE_UNKNOWN };
  59. static const int PROFILES_VP9_0[] = { FF_PROFILE_VP9_0,
  60. FF_PROFILE_UNKNOWN };
  61. static const int PROFILES_VP9_10_2[] = { FF_PROFILE_VP9_2,
  62. FF_PROFILE_UNKNOWN };
  63. typedef struct
  64. {
  65. const char* name;
  66. const GUID* guid;
  67. int codec;
  68. const int* profiles;
  69. } dxva2_mode_t;
  70. /* XXX Preferred modes must come first */
  71. static const std::vector<dxva2_mode_t> dxva2_modes = {
  72. { "MPEG2 variable-length decoder", &D3D11_DECODER_PROFILE_MPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO, PROFILES_MPEG2_MAIN },
  73. { "MPEG1/2 variable-length decoder", &D3D11_DECODER_PROFILE_MPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO, PROFILES_MPEG2_MAIN },
  74. { "MPEG2 motion compensation", &D3D11_DECODER_PROFILE_MPEG2_MOCOMP, 0, nullptr },
  75. { "MPEG2 inverse discrete cosine transform", &D3D11_DECODER_PROFILE_MPEG2_IDCT, 0, nullptr},
  76. { "MPEG-1 variable-length decoder", &D3D11_DECODER_PROFILE_MPEG1_VLD, 0, nullptr },
  77. { "H.264 variable-length decoder, film grain technology", &D3D11_DECODER_PROFILE_H264_VLD_FGT, AV_CODEC_ID_H264, PROFILES_H264_HIGH },
  78. { "H.264 variable-length decoder, no film grain technology (Intel ClearVideo)", &DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264, PROFILES_H264_HIGH },
  79. { "H.264 variable-length decoder, no film grain technology", &D3D11_DECODER_PROFILE_H264_VLD_NOFGT, AV_CODEC_ID_H264, PROFILES_H264_HIGH },
  80. { "H.264 variable-length decoder, no film grain technology, FMO/ASO", &D3D11_DECODER_PROFILE_H264_VLD_WITHFMOASO_NOFGT, AV_CODEC_ID_H264, PROFILES_H264_HIGH },
  81. { "H.264 variable-length decoder, no film grain technology, Flash", &DXVA_ModeH264_VLD_NoFGT_Flash, AV_CODEC_ID_H264, PROFILES_H264_HIGH },
  82. { "H.264 inverse discrete cosine transform, film grain technology", &D3D11_DECODER_PROFILE_H264_IDCT_FGT, 0, nullptr },
  83. { "H.264 inverse discrete cosine transform, no film grain technology", &D3D11_DECODER_PROFILE_H264_IDCT_NOFGT, 0, nullptr },
  84. { "H.264 inverse discrete cosine transform, no film grain technology (Intel)", &DXVADDI_Intel_ModeH264_C, 0, nullptr },
  85. { "H.264 motion compensation, film grain technology", &D3D11_DECODER_PROFILE_H264_MOCOMP_FGT, 0, nullptr },
  86. { "H.264 motion compensation, no film grain technology", &D3D11_DECODER_PROFILE_H264_MOCOMP_NOFGT, 0, nullptr },
  87. { "H.264 motion compensation, no film grain technology (Intel)", &DXVADDI_Intel_ModeH264_A, 0, nullptr },
  88. { "H.264 stereo high profile, mbs flag set", &D3D11_DECODER_PROFILE_H264_VLD_STEREO_PROGRESSIVE_NOFGT, 0, nullptr },
  89. { "H.264 stereo high profile", &D3D11_DECODER_PROFILE_H264_VLD_STEREO_NOFGT, 0, nullptr },
  90. { "H.264 multi-view high profile", &D3D11_DECODER_PROFILE_H264_VLD_MULTIVIEW_NOFGT, 0, nullptr },
  91. { "Windows Media Video 8 motion compensation", &D3D11_DECODER_PROFILE_WMV8_MOCOMP, 0, nullptr },
  92. { "Windows Media Video 8 post processing", &D3D11_DECODER_PROFILE_WMV8_POSTPROC, 0, nullptr },
  93. { "Windows Media Video 9 inverse discrete cosine transform", &D3D11_DECODER_PROFILE_WMV9_IDCT, 0, nullptr },
  94. { "Windows Media Video 9 motion compensation", &D3D11_DECODER_PROFILE_WMV9_MOCOMP, 0, nullptr },
  95. { "Windows Media Video 9 post processing", &D3D11_DECODER_PROFILE_WMV9_POSTPROC, 0, nullptr },
  96. { "VC-1 variable-length decoder", &D3D11_DECODER_PROFILE_VC1_VLD, AV_CODEC_ID_VC1, nullptr },
  97. { "VC-1 variable-length decoder", &D3D11_DECODER_PROFILE_VC1_VLD, AV_CODEC_ID_WMV3, nullptr },
  98. { "VC-1 variable-length decoder 2010", &D3D11_DECODER_PROFILE_VC1_D2010, AV_CODEC_ID_VC1, nullptr },
  99. { "VC-1 variable-length decoder 2010", &D3D11_DECODER_PROFILE_VC1_D2010, AV_CODEC_ID_WMV3, nullptr },
  100. { "VC-1 variable-length decoder 2 (Intel)", &DXVA_Intel_VC1_ClearVideo_2, 0, nullptr },
  101. { "VC-1 variable-length decoder (Intel)", &DXVADDI_Intel_ModeVC1_E, 0, nullptr },
  102. { "VC-1 inverse discrete cosine transform", &D3D11_DECODER_PROFILE_VC1_IDCT, 0, nullptr },
  103. { "VC-1 motion compensation", &D3D11_DECODER_PROFILE_VC1_MOCOMP, 0, nullptr },
  104. { "VC-1 post processing", &D3D11_DECODER_PROFILE_VC1_POSTPROC, 0, nullptr },
  105. { "HEVC variable-length decoder, main", &D3D11_DECODER_PROFILE_HEVC_VLD_MAIN, AV_CODEC_ID_HEVC, PROFILES_HEVC_MAIN },
  106. { "HEVC variable-length decoder, main10", &D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10, AV_CODEC_ID_HEVC, PROFILES_HEVC_MAIN10 },
  107. { "VP9 variable-length decoder, Profile 0", &D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0, AV_CODEC_ID_VP9, PROFILES_VP9_0 },
  108. { "VP9 variable-length decoder, 10bit, profile 2", &D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2, AV_CODEC_ID_VP9, PROFILES_VP9_10_2 },
  109. };
  110. // Preferred targets must be first
  111. static const DXGI_FORMAT render_targets_dxgi[] = {
  112. DXGI_FORMAT_NV12,
  113. DXGI_FORMAT_P010,
  114. DXGI_FORMAT_P016,
  115. DXGI_FORMAT_UNKNOWN
  116. };
  117. // List of PCI Device ID of ATI cards with UVD or UVD+ decoding block.
  118. static DWORD UVDDeviceID [] = {
  119. 0x95C0, // ATI Radeon HD 3400 Series (and others)
  120. 0x95C5, // ATI Radeon HD 3400 Series (and others)
  121. 0x95C4, // ATI Radeon HD 3400 Series (and others)
  122. 0x94C3, // ATI Radeon HD 3410
  123. 0x9589, // ATI Radeon HD 3600 Series (and others)
  124. 0x9598, // ATI Radeon HD 3600 Series (and others)
  125. 0x9591, // ATI Radeon HD 3600 Series (and others)
  126. 0x9501, // ATI Radeon HD 3800 Series (and others)
  127. 0x9505, // ATI Radeon HD 3800 Series (and others)
  128. 0x9507, // ATI Radeon HD 3830
  129. 0x9513, // ATI Radeon HD 3850 X2
  130. 0x950F, // ATI Radeon HD 3850 X2
  131. 0x0000
  132. };
  133. // List of PCI Device ID of nVidia cards with the macroblock width issue. More or less the VP3 block.
  134. // Per NVIDIA Accelerated Linux Graphics Driver, Appendix A Supported NVIDIA GPU Products, cards with note 1.
  135. static DWORD VP3DeviceID [] = {
  136. 0x06E0, // GeForce 9300 GE
  137. 0x06E1, // GeForce 9300 GS
  138. 0x06E2, // GeForce 8400
  139. 0x06E4, // GeForce 8400 GS
  140. 0x06E5, // GeForce 9300M GS
  141. 0x06E6, // GeForce G100
  142. 0x06E8, // GeForce 9200M GS
  143. 0x06E9, // GeForce 9300M GS
  144. 0x06EC, // GeForce G 105M
  145. 0x06EF, // GeForce G 103M
  146. 0x06F1, // GeForce G105M
  147. 0x0844, // GeForce 9100M G
  148. 0x0845, // GeForce 8200M G
  149. 0x0846, // GeForce 9200
  150. 0x0847, // GeForce 9100
  151. 0x0848, // GeForce 8300
  152. 0x0849, // GeForce 8200
  153. 0x084A, // nForce 730a
  154. 0x084B, // GeForce 9200
  155. 0x084C, // nForce 980a/780a SLI
  156. 0x084D, // nForce 750a SLI
  157. 0x0860, // GeForce 9400
  158. 0x0861, // GeForce 9400
  159. 0x0862, // GeForce 9400M G
  160. 0x0863, // GeForce 9400M
  161. 0x0864, // GeForce 9300
  162. 0x0865, // ION
  163. 0x0866, // GeForce 9400M G
  164. 0x0867, // GeForce 9400
  165. 0x0868, // nForce 760i SLI
  166. 0x086A, // GeForce 9400
  167. 0x086C, // GeForce 9300 / nForce 730i
  168. 0x086D, // GeForce 9200
  169. 0x086E, // GeForce 9100M G
  170. 0x086F, // GeForce 8200M G
  171. 0x0870, // GeForce 9400M
  172. 0x0871, // GeForce 9200
  173. 0x0872, // GeForce G102M
  174. 0x0873, // GeForce G102M
  175. 0x0874, // ION
  176. 0x0876, // ION
  177. 0x087A, // GeForce 9400
  178. 0x087D, // ION
  179. 0x087E, // ION LE
  180. 0x087F, // ION LE
  181. 0x0000
  182. };
  183. static std::string GUIDToString(const GUID& guid)
  184. {
  185. std::string buffer = StringUtils::Format(
  186. "{:08X}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", guid.Data1,
  187. guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
  188. guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
  189. return buffer;
  190. }
  191. static const dxva2_mode_t* dxva2_find_mode(const GUID* guid)
  192. {
  193. for (const dxva2_mode_t& mode : dxva2_modes)
  194. {
  195. if (IsEqualGUID(*mode.guid, *guid))
  196. return &mode;
  197. }
  198. return nullptr;
  199. }
  200. //-----------------------------------------------------------------------------
  201. // DXVA Context
  202. //-----------------------------------------------------------------------------
  203. CContext::weak_ptr CContext::m_context;
  204. CCriticalSection CContext::m_section;
  205. CContext::~CContext()
  206. {
  207. Close();
  208. }
  209. void CContext::Release(CDecoder* decoder)
  210. {
  211. CSingleLock lock(m_section);
  212. const auto it = std::find(m_decoders.begin(), m_decoders.end(), decoder);
  213. if (it != m_decoders.end())
  214. m_decoders.erase(it);
  215. }
  216. void CContext::Close()
  217. {
  218. CLog::LogFunction(LOGINFO, "DXVA", "closing decoder context.");
  219. DestroyContext();
  220. }
  221. CContext::shared_ptr CContext::EnsureContext(CDecoder* decoder)
  222. {
  223. CSingleLock lock(m_section);
  224. auto context = m_context.lock();
  225. if (context)
  226. {
  227. if (!context->IsValidDecoder(decoder))
  228. context->m_decoders.push_back(decoder);
  229. return context;
  230. }
  231. context.reset(new CContext());
  232. {
  233. if (!context->CreateContext())
  234. return shared_ptr();
  235. m_context = context;
  236. }
  237. return EnsureContext(decoder);
  238. }
  239. bool CContext::CreateContext()
  240. {
  241. HRESULT hr = E_FAIL;
  242. ComPtr<ID3D11Device> pD3DDevice;
  243. ComPtr<ID3D11DeviceContext> pD3DDeviceContext;
  244. m_sharingAllowed = DX::DeviceResources::Get()->IsNV12SharedTexturesSupported();
  245. if (m_sharingAllowed)
  246. {
  247. CLog::LogF(LOGINFO, "creating discrete d3d11va device for decoding.");
  248. std::vector<D3D_FEATURE_LEVEL> featureLevels;
  249. if (CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin10))
  250. {
  251. featureLevels.push_back(D3D_FEATURE_LEVEL_12_1);
  252. featureLevels.push_back(D3D_FEATURE_LEVEL_12_0);
  253. }
  254. if (CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin8))
  255. featureLevels.push_back(D3D_FEATURE_LEVEL_11_1);
  256. featureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
  257. featureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
  258. featureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
  259. featureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
  260. featureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
  261. featureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
  262. hr = D3D11CreateDevice(DX::DeviceResources::Get()->GetAdapter(), D3D_DRIVER_TYPE_UNKNOWN,
  263. nullptr, D3D11_CREATE_DEVICE_VIDEO_SUPPORT, featureLevels.data(),
  264. featureLevels.size(), D3D11_SDK_VERSION, &pD3DDevice, nullptr,
  265. &pD3DDeviceContext);
  266. if (FAILED(hr))
  267. {
  268. CLog::LogF(LOGWARNING, "unable to create device for decoding, fallback to using app device.");
  269. m_sharingAllowed = false;
  270. }
  271. }
  272. else
  273. {
  274. CLog::LogF(LOGWARNING, "using app d3d11 device for decoding due extended NV12 shared "
  275. "textures it's not supported.");
  276. }
  277. if (FAILED(hr))
  278. {
  279. pD3DDevice = DX::DeviceResources::Get()->GetD3DDevice();
  280. pD3DDeviceContext = DX::DeviceResources::Get()->GetImmediateContext();
  281. }
  282. if (FAILED(pD3DDevice.As(&m_pD3D11Device)) || FAILED(pD3DDeviceContext.As(&m_pD3D11Context)))
  283. {
  284. CLog::LogF(LOGWARNING, "failed to get Video Device and Context.");
  285. return false;
  286. }
  287. if (FAILED(hr) || !m_sharingAllowed)
  288. {
  289. // enable multi-threaded protection only if is used same d3d11 device for rendering and decoding
  290. ComPtr<ID3D11Multithread> multithread;
  291. hr = pD3DDevice.As(&multithread);
  292. if (SUCCEEDED(hr))
  293. multithread->SetMultithreadProtected(1);
  294. }
  295. QueryCaps();
  296. // Some older Ati devices can only open a single decoder at a given time
  297. std::string renderer = DX::Windowing()->GetRenderRenderer();
  298. if (renderer.find("Radeon HD 2") != std::string::npos ||
  299. renderer.find("Radeon HD 3") != std::string::npos ||
  300. renderer.find("Radeon HD 4") != std::string::npos ||
  301. renderer.find("Radeon HD 5") != std::string::npos)
  302. {
  303. m_atiWorkaround = true;
  304. }
  305. // Sets high priority process for smooth playback in all circumstances
  306. SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  307. return true;
  308. }
  309. void CContext::DestroyContext()
  310. {
  311. delete[] m_input_list;
  312. m_pD3D11Device = nullptr;
  313. m_pD3D11Context = nullptr;
  314. // Restores normal priority process
  315. SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
  316. }
  317. void CContext::QueryCaps()
  318. {
  319. m_input_count = m_pD3D11Device->GetVideoDecoderProfileCount();
  320. m_input_list = new GUID[m_input_count];
  321. for (unsigned i = 0; i < m_input_count; i++)
  322. {
  323. if (FAILED(m_pD3D11Device->GetVideoDecoderProfile(i, &m_input_list[i])))
  324. {
  325. CLog::LogFunction(LOGINFO, "DXVA", "failed getting video decoder profile");
  326. return;
  327. }
  328. const dxva2_mode_t* mode = dxva2_find_mode(&m_input_list[i]);
  329. if (mode)
  330. CLog::LogFunction(LOGDEBUG, "DXVA", "supports '{}'", mode->name);
  331. else
  332. CLog::LogFunction(LOGDEBUG, "DXVA", "supports {}", GUIDToString(m_input_list[i]));
  333. }
  334. }
  335. bool CContext::GetFormatAndConfig(AVCodecContext* avctx, D3D11_VIDEO_DECODER_DESC &format, D3D11_VIDEO_DECODER_CONFIG &config) const
  336. {
  337. format.OutputFormat = DXGI_FORMAT_UNKNOWN;
  338. // iterate through our predefined dxva modes and find the first matching for desired codec
  339. // once we found a mode, get a target we support in render_targets_dxgi DXGI_FORMAT_UNKNOWN
  340. for (const dxva2_mode_t& mode : dxva2_modes)
  341. {
  342. if (mode.codec != avctx->codec_id)
  343. continue;
  344. bool supported = false;
  345. for (unsigned i = 0; i < m_input_count && !supported; i++)
  346. {
  347. supported = IsEqualGUID(m_input_list[i], *mode.guid) != 0;
  348. }
  349. if (supported)
  350. {
  351. // check profiles
  352. supported = false;
  353. if (mode.profiles == nullptr)
  354. supported = true;
  355. else if (avctx->profile == FF_PROFILE_UNKNOWN)
  356. supported = true;
  357. else
  358. for (const int* pProfile = &mode.profiles[0]; *pProfile != FF_PROFILE_UNKNOWN; ++pProfile)
  359. {
  360. if (*pProfile == avctx->profile)
  361. {
  362. supported = true;
  363. break;
  364. }
  365. }
  366. if (!supported)
  367. CLog::LogFunction(LOGDEBUG, "DXVA", "Unsupported profile {} for {}.", avctx->profile,
  368. mode.name);
  369. }
  370. if (!supported)
  371. continue;
  372. CLog::LogFunction(LOGDEBUG, "DXVA", "trying '{}'.", mode.name);
  373. for (unsigned j = 0; render_targets_dxgi[j]; ++j)
  374. {
  375. bool bHighBits = (avctx->codec_id == AV_CODEC_ID_HEVC && (avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 || avctx->profile == FF_PROFILE_HEVC_MAIN_10))
  376. || (avctx->codec_id == AV_CODEC_ID_VP9 && (avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 || avctx->profile == FF_PROFILE_VP9_2));
  377. if (bHighBits && render_targets_dxgi[j] < DXGI_FORMAT_P010)
  378. continue;
  379. BOOL format_supported = FALSE;
  380. HRESULT res = m_pD3D11Device->CheckVideoDecoderFormat(mode.guid, render_targets_dxgi[j], &format_supported);
  381. if (FAILED(res) || !format_supported)
  382. {
  383. CLog::LogFunction(LOGINFO, "DXVA", "Output format {} is not supported by '{}'",
  384. render_targets_dxgi[j], mode.name);
  385. continue;
  386. }
  387. // check decoder config
  388. D3D11_VIDEO_DECODER_DESC checkFormat = {*mode.guid, static_cast<UINT>(avctx->coded_width),
  389. static_cast<UINT>(avctx->coded_height),
  390. render_targets_dxgi[j]};
  391. if (!GetConfig(checkFormat, config))
  392. continue;
  393. // config is found, update decoder description
  394. format.Guid = *mode.guid;
  395. format.OutputFormat = render_targets_dxgi[j];
  396. format.SampleWidth = avctx->coded_width;
  397. format.SampleHeight = avctx->coded_height;
  398. return true;
  399. }
  400. }
  401. return false;
  402. }
  403. bool CContext::GetConfig(const D3D11_VIDEO_DECODER_DESC &format, D3D11_VIDEO_DECODER_CONFIG &config) const
  404. {
  405. // find what decode configs are available
  406. UINT cfg_count = 0;
  407. if (FAILED(m_pD3D11Device->GetVideoDecoderConfigCount(&format, &cfg_count)))
  408. {
  409. CLog::LogF(LOGINFO, "failed getting decoder configuration count.");
  410. return false;
  411. }
  412. if (!cfg_count)
  413. {
  414. CLog::LogF(LOGINFO, "no decoder configuration possible for {}x{} ({}).", format.SampleWidth,
  415. format.SampleHeight, format.OutputFormat);
  416. return false;
  417. }
  418. config = {};
  419. const unsigned bitstream = 2; // ConfigBitstreamRaw = 2 is required for Poulsbo and handles skipping better with nVidia
  420. for (unsigned i = 0; i< cfg_count; i++)
  421. {
  422. D3D11_VIDEO_DECODER_CONFIG pConfig = {};
  423. if (FAILED(m_pD3D11Device->GetVideoDecoderConfig(&format, i, &pConfig)))
  424. {
  425. CLog::LogF(LOGINFO, "failed getting decoder configuration.");
  426. return false;
  427. }
  428. CLog::LogFunction(
  429. LOGDEBUG, "DXVA", "config {}: bitstream type {}{}.", i, pConfig.ConfigBitstreamRaw,
  430. IsEqualGUID(pConfig.guidConfigBitstreamEncryption, DXVA_NoEncrypt) ? "" : ", encrypted");
  431. // select first available
  432. if (config.ConfigBitstreamRaw == 0 && pConfig.ConfigBitstreamRaw != 0)
  433. config = pConfig;
  434. // override with preferred if found
  435. if (config.ConfigBitstreamRaw != bitstream && pConfig.ConfigBitstreamRaw == bitstream)
  436. config = pConfig;
  437. }
  438. if (!config.ConfigBitstreamRaw)
  439. {
  440. CLog::LogFunction(LOGDEBUG, "DXVA", "failed to find a raw input bitstream.");
  441. return false;
  442. }
  443. return true;
  444. }
  445. bool CContext::CreateSurfaces(const D3D11_VIDEO_DECODER_DESC& format, uint32_t count,
  446. uint32_t alignment, ID3D11VideoDecoderOutputView** surfaces,
  447. HANDLE* pHandle, bool trueShared) const
  448. {
  449. HRESULT hr = S_OK;
  450. ComPtr<ID3D11Device> pD3DDevice;
  451. ComPtr<ID3D11DeviceContext> pD3DDeviceContext;
  452. ComPtr<ID3D11DeviceContext1> pD3DDeviceContext1;
  453. m_pD3D11Context->GetDevice(&pD3DDevice);
  454. pD3DDevice->GetImmediateContext(&pD3DDeviceContext);
  455. pD3DDeviceContext.As(&pD3DDeviceContext1);
  456. CD3D11_TEXTURE2D_DESC texDesc(format.OutputFormat,
  457. FFALIGN(format.SampleWidth, alignment),
  458. FFALIGN(format.SampleHeight, alignment),
  459. count, 1, D3D11_BIND_DECODER);
  460. UINT supported;
  461. if (SUCCEEDED(pD3DDevice->CheckFormatSupport(format.OutputFormat, &supported)) &&
  462. (supported & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
  463. {
  464. texDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
  465. }
  466. if (trueShared)
  467. {
  468. texDesc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
  469. }
  470. CLog::LogFunction(LOGDEBUG, "DXVA", "allocating {} surfaces with format {}.", count,
  471. format.OutputFormat);
  472. ComPtr<ID3D11Texture2D> texture;
  473. if (FAILED(pD3DDevice->CreateTexture2D(&texDesc, NULL, texture.GetAddressOf())))
  474. {
  475. CLog::LogF(LOGERROR, "failed creating decoder texture array.");
  476. return false;
  477. }
  478. // acquire shared handle once
  479. if (trueShared && pHandle)
  480. {
  481. ComPtr<IDXGIResource> dxgiResource;
  482. if (FAILED(texture.As(&dxgiResource)) || FAILED(dxgiResource->GetSharedHandle(pHandle)))
  483. {
  484. CLog::LogF(LOGERROR, "unable to get shared handle for texture");
  485. *pHandle = INVALID_HANDLE_VALUE;
  486. }
  487. }
  488. D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC vdovDesc = {
  489. format.Guid,
  490. D3D11_VDOV_DIMENSION_TEXTURE2D,
  491. { 0 }
  492. };
  493. // For video views with YUV or YCbBr formats, ClearView doesn't
  494. // convert color values but assumes UINT texture format
  495. float clearColor[] = {0.f, 127.f, 127.f, 255.f}; // black color in YUV
  496. size_t i;
  497. for (i = 0; i < count; ++i)
  498. {
  499. vdovDesc.Texture2D.ArraySlice = D3D11CalcSubresource(0, i, texDesc.MipLevels);
  500. hr = m_pD3D11Device->CreateVideoDecoderOutputView(texture.Get(), &vdovDesc, &surfaces[i]);
  501. if (FAILED(hr))
  502. {
  503. CLog::LogF(LOGERROR, "failed creating surfaces.");
  504. break;
  505. }
  506. if (pD3DDeviceContext1)
  507. pD3DDeviceContext1->ClearView(surfaces[i], clearColor, nullptr, 0);
  508. }
  509. if (FAILED(hr))
  510. {
  511. for (size_t j = 0; j < i && surfaces[j]; ++j)
  512. {
  513. surfaces[j]->Release();
  514. surfaces[j] = nullptr;
  515. };
  516. }
  517. return SUCCEEDED(hr);
  518. }
  519. bool CContext::CreateDecoder(const D3D11_VIDEO_DECODER_DESC &format, const D3D11_VIDEO_DECODER_CONFIG &config
  520. , ID3D11VideoDecoder **decoder, ID3D11VideoContext **context)
  521. {
  522. CSingleLock lock(m_section);
  523. int retry = 0;
  524. while (retry < 2)
  525. {
  526. if (!m_atiWorkaround || retry > 0)
  527. {
  528. ComPtr<ID3D11VideoDecoder> pDecoder;
  529. HRESULT res = m_pD3D11Device->CreateVideoDecoder(&format, &config, pDecoder.GetAddressOf());
  530. if (!FAILED(res))
  531. {
  532. *decoder = pDecoder.Detach();
  533. return SUCCEEDED(m_pD3D11Context.CopyTo(context));
  534. }
  535. }
  536. if (retry == 0)
  537. {
  538. CLog::LogF(LOGINFO, "hw may not support multiple decoders, releasing existing ones.");
  539. for (auto& m_decoder : m_decoders)
  540. m_decoder->CloseDXVADecoder();
  541. }
  542. retry++;
  543. }
  544. CLog::LogF(LOGERROR, "failed creating decoder.");
  545. return false;
  546. }
  547. bool CContext::IsValidDecoder(CDecoder* decoder)
  548. {
  549. return std::find(m_decoders.begin(), m_decoders.end(), decoder) != m_decoders.end();
  550. }
  551. bool CContext::Check() const
  552. {
  553. if (!m_sharingAllowed)
  554. return true;
  555. ComPtr<ID3D11Device> pDevice;
  556. m_pD3D11Context->GetDevice(&pDevice);
  557. return SUCCEEDED(pDevice->GetDeviceRemovedReason());
  558. }
  559. bool CContext::Reset()
  560. {
  561. if (Check())
  562. {
  563. DXGI_ADAPTER_DESC appDesc = {};
  564. DX::DeviceResources::Get()->GetAdapterDesc(&appDesc);
  565. ComPtr<IDXGIDevice> ctxDevice;
  566. ComPtr<IDXGIAdapter> ctxAdapter;
  567. if (SUCCEEDED(m_pD3D11Device.As(&ctxDevice)) &&
  568. SUCCEEDED(ctxDevice->GetAdapter(&ctxAdapter)))
  569. {
  570. DXGI_ADAPTER_DESC ctxDesc = {};
  571. ctxAdapter->GetDesc(&ctxDesc);
  572. if (appDesc.AdapterLuid.HighPart == ctxDesc.AdapterLuid.HighPart &&
  573. appDesc.AdapterLuid.LowPart == ctxDesc.AdapterLuid.LowPart)
  574. {
  575. // 1. we have valid device
  576. // 2. we are on the same adapter
  577. // 3. don't reset context.
  578. return true;
  579. }
  580. }
  581. }
  582. DestroyContext();
  583. return CreateContext();
  584. }
  585. //-----------------------------------------------------------------------------
  586. // DXVA::CVideoBuffer
  587. //-----------------------------------------------------------------------------
  588. DXVA::CVideoBuffer::CVideoBuffer(int id)
  589. : ::CVideoBuffer(id)
  590. {
  591. m_pixFormat = AV_PIX_FMT_D3D11VA_VLD;
  592. m_pFrame = av_frame_alloc();
  593. }
  594. DXVA::CVideoBuffer::~CVideoBuffer()
  595. {
  596. av_frame_free(&m_pFrame);
  597. }
  598. void DXVA::CVideoBuffer::Initialize(CDecoder* decoder)
  599. {
  600. width = FFALIGN(decoder->m_format.SampleWidth, decoder->m_surface_alignment);
  601. height = FFALIGN(decoder->m_format.SampleHeight, decoder->m_surface_alignment);
  602. format = decoder->m_format.OutputFormat;
  603. }
  604. HRESULT DXVA::CVideoBuffer::GetResource(ID3D11Resource** ppResource)
  605. {
  606. if (!view)
  607. return E_NOT_SET;
  608. view->GetResource(ppResource);
  609. return S_OK;
  610. }
  611. unsigned DXVA::CVideoBuffer::GetIdx()
  612. {
  613. D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC vpivd = {};
  614. ComPtr<ID3D11VideoDecoderOutputView> pView = reinterpret_cast<ID3D11VideoDecoderOutputView*>(view);
  615. pView->GetDesc(&vpivd);
  616. return vpivd.Texture2D.ArraySlice;
  617. }
  618. void DXVA::CVideoBuffer::SetRef(AVFrame* frame)
  619. {
  620. av_frame_unref(m_pFrame);
  621. av_frame_ref(m_pFrame, frame);
  622. view = reinterpret_cast<ID3D11View*>(frame->data[3]);
  623. }
  624. void DXVA::CVideoBuffer::Unref()
  625. {
  626. view = nullptr;
  627. av_frame_unref(m_pFrame);
  628. }
  629. HRESULT CVideoBufferShared::GetResource(ID3D11Resource** ppResource)
  630. {
  631. HRESULT hr = S_OK;
  632. if (handle == INVALID_HANDLE_VALUE)
  633. return E_HANDLE;
  634. if (!m_sharedRes)
  635. {
  636. // open resource on app device
  637. ComPtr<ID3D11Device> pD3DDevice = DX::DeviceResources::Get()->GetD3DDevice();
  638. hr = pD3DDevice->OpenSharedResource(handle, __uuidof(ID3D11Resource), &m_sharedRes);
  639. }
  640. if (SUCCEEDED(hr))
  641. hr = m_sharedRes.CopyTo(ppResource);
  642. return hr;
  643. }
  644. void CVideoBufferShared::Initialize(CDecoder* decoder)
  645. {
  646. CVideoBuffer::Initialize(decoder);
  647. if (handle == INVALID_HANDLE_VALUE)
  648. handle = decoder->m_sharedHandle;
  649. }
  650. void CVideoBufferCopy::Initialize(CDecoder* decoder)
  651. {
  652. CVideoBuffer::Initialize(decoder);
  653. if (!m_copyRes)
  654. {
  655. ComPtr<ID3D11Device> pDevice;
  656. ComPtr<ID3D11DeviceContext> pDeviceContext;
  657. ComPtr<ID3D11Texture2D> pDecoderTexture;
  658. ComPtr<ID3D11Texture2D> pCopyTexture;
  659. ComPtr<IDXGIResource> pDXGIResource;
  660. ComPtr<ID3D11Resource> pResource;
  661. decoder->m_pD3D11Context->GetDevice(&pDevice);
  662. pDevice->GetImmediateContext(&pDeviceContext);
  663. if (FAILED(CVideoBuffer::GetResource(&pResource)))
  664. {
  665. CLog::LogF(LOGDEBUG, "unable to get decoder resource");
  666. return;
  667. }
  668. if (FAILED(pResource.As(&pDecoderTexture)))
  669. {
  670. CLog::LogF(LOGDEBUG, "unable to get decoder texture");
  671. return;
  672. }
  673. D3D11_TEXTURE2D_DESC desc;
  674. pDecoderTexture->GetDesc(&desc);
  675. desc.ArraySize = 1;
  676. desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
  677. desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
  678. if (FAILED(pDevice->CreateTexture2D(&desc, nullptr, &pCopyTexture)))
  679. {
  680. CLog::LogF(LOGDEBUG, "unable to create copy texture");
  681. return;
  682. }
  683. if (FAILED(pCopyTexture.As(&pDXGIResource)))
  684. {
  685. CLog::LogF(LOGDEBUG, "unable to get DXGI resource for copy texture");
  686. return;
  687. }
  688. HANDLE shared_handle;
  689. if (FAILED(pDXGIResource->GetSharedHandle(&shared_handle)))
  690. {
  691. CLog::LogF(LOGDEBUG, "unable to get shared handle");
  692. return;
  693. }
  694. handle = shared_handle;
  695. pCopyTexture.As(&m_copyRes);
  696. pResource.As(&m_pResource);
  697. pDeviceContext.As(&m_pDeviceContext);
  698. }
  699. if (m_copyRes)
  700. {
  701. // sends commands to GPU (ensures that the last decoded image is ready)
  702. m_pDeviceContext->Flush();
  703. // copy decoder surface on decoder device
  704. m_pDeviceContext->CopySubresourceRegion(m_copyRes.Get(), 0, 0, 0, 0, m_pResource.Get(),
  705. CVideoBuffer::GetIdx(), nullptr);
  706. if (decoder->m_DVDWorkaround) // DVDs menus/stills need extra Flush()
  707. m_pDeviceContext->Flush();
  708. }
  709. }
  710. //-----------------------------------------------------------------------------
  711. // DXVA::CVideoBufferPool
  712. //-----------------------------------------------------------------------------
  713. CVideoBufferPool::CVideoBufferPool() = default;
  714. CVideoBufferPool::~CVideoBufferPool()
  715. {
  716. CLog::LogF(LOGDEBUG, "destructing buffer pool.");
  717. Reset();
  718. }
  719. ::CVideoBuffer* CVideoBufferPool::Get()
  720. {
  721. CSingleLock lock(m_section);
  722. CVideoBuffer* retPic;
  723. if (!m_freeOut.empty())
  724. {
  725. const size_t idx = m_freeOut.front();
  726. m_freeOut.pop_front();
  727. retPic = m_out[idx];
  728. }
  729. else
  730. {
  731. const size_t idx = m_out.size();
  732. retPic = CreateBuffer(idx);
  733. m_out.push_back(retPic);
  734. }
  735. retPic->Acquire(GetPtr());
  736. return retPic;
  737. }
  738. void CVideoBufferPool::Return(int id)
  739. {
  740. CSingleLock lock(m_section);
  741. auto buf = m_out[id];
  742. buf->Unref();
  743. m_freeOut.push_back(id);
  744. }
  745. void CVideoBufferPool::AddView(ID3D11View* view)
  746. {
  747. CSingleLock lock(m_section);
  748. const size_t idx = m_views.size();
  749. m_views.push_back(view);
  750. m_freeViews.push_back(idx);
  751. }
  752. bool CVideoBufferPool::IsValid(ID3D11View* view)
  753. {
  754. CSingleLock lock(m_section);
  755. return std::find(m_views.begin(), m_views.end(), view) != m_views.end();
  756. }
  757. bool CVideoBufferPool::ReturnView(ID3D11View* view)
  758. {
  759. CSingleLock lock(m_section);
  760. const auto it = std::find(m_views.begin(), m_views.end(), view);
  761. if (it == m_views.end())
  762. return false;
  763. const size_t idx = it - m_views.begin();
  764. m_freeViews.push_back(idx);
  765. return true;
  766. }
  767. ID3D11View* CVideoBufferPool::GetView()
  768. {
  769. CSingleLock lock(m_section);
  770. if (!m_freeViews.empty())
  771. {
  772. const size_t idx = m_freeViews.front();
  773. m_freeViews.pop_front();
  774. return m_views[idx];
  775. }
  776. return nullptr;
  777. }
  778. void CVideoBufferPool::Reset()
  779. {
  780. CSingleLock lock(m_section);
  781. for (auto v : m_views)
  782. if (v)
  783. v->Release();
  784. for (auto buf : m_out)
  785. delete buf;
  786. m_views.clear();
  787. m_freeViews.clear();
  788. m_out.clear();
  789. m_freeOut.clear();
  790. }
  791. size_t CVideoBufferPool::Size()
  792. {
  793. CSingleLock lock(m_section);
  794. return m_views.size();
  795. }
  796. bool CVideoBufferPool::HasFree()
  797. {
  798. CSingleLock lock(m_section);
  799. return !m_freeViews.empty();
  800. }
  801. bool CVideoBufferPool::HasRefs()
  802. {
  803. CSingleLock lock(m_section);
  804. // out buffers hold views
  805. const size_t buffRefs = m_out.size() - m_freeOut.size();
  806. // ffmpeg refs = total - free - out refs
  807. return m_freeViews.size() != m_views.size() - buffRefs;
  808. }
  809. //-----------------------------------------------------------------------------
  810. // DXVA::CDecoder
  811. //-----------------------------------------------------------------------------
  812. IHardwareDecoder* CDecoder::Create(CDVDStreamInfo &hint, CProcessInfo &processInfo, AVPixelFormat fmt)
  813. {
  814. if (Supports(fmt) && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
  815. CSettings::SETTING_VIDEOPLAYER_USEDXVA2))
  816. return new CDecoder(processInfo);
  817. return nullptr;
  818. }
  819. bool CDecoder::Register()
  820. {
  821. CDVDFactoryCodec::RegisterHWAccel("dxva", Create);
  822. return true;
  823. }
  824. CDecoder::CDecoder(CProcessInfo& processInfo)
  825. : m_processInfo(processInfo)
  826. {
  827. m_event.Set();
  828. m_avD3D11Context = av_d3d11va_alloc_context();
  829. m_avD3D11Context->cfg = reinterpret_cast<D3D11_VIDEO_DECODER_CONFIG*>(av_mallocz(sizeof(D3D11_VIDEO_DECODER_CONFIG)));
  830. m_avD3D11Context->surface = reinterpret_cast<ID3D11VideoDecoderOutputView**>(av_mallocz_array(32, sizeof(ID3D11VideoDecoderOutputView*)));
  831. m_bufferPool.reset();
  832. DX::Windowing()->Register(this);
  833. }
  834. CDecoder::~CDecoder()
  835. {
  836. CLog::LogF(LOGDEBUG, "destructing decoder, {}.", fmt::ptr(this));
  837. DX::Windowing()->Unregister(this);
  838. Close();
  839. av_freep(&m_avD3D11Context->surface);
  840. av_freep(&m_avD3D11Context->cfg);
  841. av_freep(&m_avD3D11Context);
  842. }
  843. long CDecoder::Release()
  844. {
  845. // if ffmpeg holds any references, flush buffers
  846. if (m_bufferPool && m_bufferPool->HasRefs())
  847. avcodec_flush_buffers(m_avCtx);
  848. return IHardwareDecoder::Release();
  849. }
  850. void CDecoder::Close()
  851. {
  852. CSingleLock lock(m_section);
  853. m_pD3D11Decoder = nullptr;
  854. m_pD3D11Context = nullptr;
  855. if (m_videoBuffer)
  856. {
  857. m_videoBuffer->Release();
  858. m_videoBuffer = nullptr;
  859. }
  860. m_format = {};
  861. m_sharedHandle = INVALID_HANDLE_VALUE;
  862. if (m_dxvaContext)
  863. {
  864. auto dxva_context = m_dxvaContext;
  865. CLog::LogF(LOGINFO, "closing decoder.");
  866. m_dxvaContext = nullptr;
  867. dxva_context->Release(this);
  868. }
  869. }
  870. static bool CheckH264L41(AVCodecContext* avctx)
  871. {
  872. unsigned widthmbs = (avctx->coded_width + 15) / 16; // width in macroblocks
  873. unsigned heightmbs = (avctx->coded_height + 15) / 16; // height in macroblocks
  874. unsigned maxdpbmbs = 32768; // Decoded Picture Buffer (DPB) capacity in macroblocks for L4.1
  875. return avctx->refs * widthmbs * heightmbs <= maxdpbmbs;
  876. }
  877. static bool IsL41LimitedATI()
  878. {
  879. DXGI_ADAPTER_DESC AIdentifier = {};
  880. DX::DeviceResources::Get()->GetAdapterDesc(&AIdentifier);
  881. if (AIdentifier.VendorId == PCIV_ATI)
  882. {
  883. for (unsigned idx = 0; UVDDeviceID[idx] != 0; idx++)
  884. {
  885. if (UVDDeviceID[idx] == AIdentifier.DeviceId)
  886. return true;
  887. }
  888. }
  889. return false;
  890. }
  891. static bool HasVP3WidthBug(AVCodecContext* avctx)
  892. {
  893. // Some nVidia VP3 hardware cannot do certain macroblock widths
  894. DXGI_ADAPTER_DESC AIdentifier = {};
  895. DX::DeviceResources::Get()->GetAdapterDesc(&AIdentifier);
  896. if (AIdentifier.VendorId == PCIV_nVidia &&
  897. !CDVDCodecUtils::IsVP3CompatibleWidth(avctx->coded_width))
  898. {
  899. // Find the card in a known list of problematic VP3 hardware
  900. for (unsigned idx = 0; VP3DeviceID[idx] != 0; idx++)
  901. if (VP3DeviceID[idx] == AIdentifier.DeviceId)
  902. return true;
  903. }
  904. return false;
  905. }
  906. static bool HasATIMP2Bug(AVCodecContext* avctx)
  907. {
  908. DXGI_ADAPTER_DESC AIdentifier = {};
  909. DX::DeviceResources::Get()->GetAdapterDesc(&AIdentifier);
  910. if (AIdentifier.VendorId != PCIV_ATI)
  911. return false;
  912. // AMD/ATI card doesn't like some SD MPEG2 content
  913. // here are params of these videos
  914. return avctx->height <= 576
  915. && avctx->colorspace == AVCOL_SPC_BT470BG
  916. && avctx->color_primaries == AVCOL_PRI_BT470BG
  917. && avctx->color_trc == AVCOL_TRC_GAMMA28;
  918. }
  919. static bool CheckCompatibility(AVCodecContext* avctx)
  920. {
  921. if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && HasATIMP2Bug(avctx))
  922. return false;
  923. // The incompatibilities are all for H264
  924. if (avctx->codec_id != AV_CODEC_ID_H264)
  925. return true;
  926. // Macroblock width incompatibility
  927. if (HasVP3WidthBug(avctx))
  928. {
  929. CLog::LogFunction(LOGWARNING, "DXVA",
  930. "width {} is not supported with nVidia VP3 hardware. DXVA will not be used.",
  931. avctx->coded_width);
  932. return false;
  933. }
  934. // Check for hardware limited to H264 L4.1 (ie Bluray).
  935. // No advanced settings: autodetect.
  936. // The advanced setting lets the user override the autodetection (in case of false positive or negative)
  937. bool checkcompat;
  938. if (!CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_DXVACheckCompatibilityPresent)
  939. checkcompat = IsL41LimitedATI(); // ATI UVD and UVD+ cards can only do L4.1 - corresponds roughly to series 3xxx
  940. else
  941. checkcompat = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_DXVACheckCompatibility;
  942. if (checkcompat && !CheckH264L41(avctx))
  943. {
  944. CLog::LogFunction(LOGWARNING, "DXVA", "compatibility check: video exceeds L4.1. DXVA will not be used.");
  945. return false;
  946. }
  947. return true;
  948. }
  949. bool CDecoder::Open(AVCodecContext* avctx, AVCodecContext* mainctx, enum AVPixelFormat fmt)
  950. {
  951. if (!CheckCompatibility(avctx))
  952. return false;
  953. // DVDs menus/stills need extra Flush() after copy texture
  954. if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && avctx->height <= 576)
  955. m_DVDWorkaround = true;
  956. CSingleLock lock(m_section);
  957. Close();
  958. if (m_state == DXVA_LOST)
  959. {
  960. CLog::LogFunction(LOGDEBUG, "DXVA", "device is in lost state, we can't start.");
  961. return false;
  962. }
  963. CLog::LogFunction(LOGDEBUG, "DXVA", "open decoder.");
  964. m_dxvaContext = CContext::EnsureContext(this);
  965. if (!m_dxvaContext)
  966. return false;
  967. if (!m_dxvaContext->GetFormatAndConfig(avctx, m_format, *m_avD3D11Context->cfg))
  968. {
  969. CLog::LogFunction(LOGDEBUG, "DXVA", "unable to find an input/output format combination.");
  970. return false;
  971. }
  972. CLog::LogFunction(LOGDEBUG, "DXVA", "selected output format: {}.", m_format.OutputFormat);
  973. CLog::LogFunction(LOGDEBUG, "DXVA", "source requires {} references.", avctx->refs);
  974. if (m_format.Guid == DXVADDI_Intel_ModeH264_E && avctx->refs > 11)
  975. {
  976. const dxva2_mode_t* mode = dxva2_find_mode(&m_format.Guid);
  977. CLog::LogFunction(LOGWARNING, "DXVA", "too many references {} for selected decoder '{}'.",
  978. avctx->refs, mode->name);
  979. return false;
  980. }
  981. if (6 > m_shared)
  982. m_shared = 6;
  983. m_refs = 2 + m_shared; // 1 decode + 1 safety + display
  984. m_surface_alignment = 16;
  985. DXGI_ADAPTER_DESC ad = {};
  986. DX::DeviceResources::Get()->GetAdapterDesc(&ad);
  987. size_t videoMem = ad.SharedSystemMemory + ad.DedicatedVideoMemory + ad.DedicatedSystemMemory;
  988. CLog::LogF(LOGINFO, "Total video memory available is {} MB (dedicated = {} MB, shared = {} MB)",
  989. videoMem / MB, (ad.DedicatedVideoMemory + ad.DedicatedSystemMemory) / MB,
  990. ad.SharedSystemMemory / MB);
  991. switch (avctx->codec_id)
  992. {
  993. case AV_CODEC_ID_MPEG2VIDEO:
  994. /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
  995. but it causes issues for H.264 on certain AMD GPUs..... */
  996. m_surface_alignment = 32;
  997. m_refs += 2;
  998. break;
  999. case AV_CODEC_ID_HEVC:
  1000. /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
  1001. all coding features have enough room to work with */
  1002. m_surface_alignment = 128;
  1003. // a driver may use multi-thread decoding internally (PC only)
  1004. if (CSysInfo::GetWindowsDeviceFamily() != CSysInfo::Xbox)
  1005. m_refs += CServiceBroker::GetCPUInfo()->GetCPUCount();
  1006. // by specification hevc decoder can hold up to 8 unique refs
  1007. // ffmpeg may report only 1 refs frame when is unknown or not present in headers
  1008. m_refs += (avctx->refs > 1) ? avctx->refs : 8;
  1009. break;
  1010. case AV_CODEC_ID_H264:
  1011. // by specification h264 decoder can hold up to 16 unique refs
  1012. m_refs += avctx->refs ? avctx->refs : 16;
  1013. break;
  1014. case AV_CODEC_ID_VP9:
  1015. m_refs += 8;
  1016. break;
  1017. default:
  1018. m_refs += 2;
  1019. }
  1020. if (avctx->active_thread_type & FF_THREAD_FRAME)
  1021. m_refs += avctx->thread_count;
  1022. // Limit decoder surfaces to 32 maximum in any case. Since with some 16 cores / 32 threads
  1023. // new CPU's (Ryzen 5950x) this number may be higher than what the graphics card can handle.
  1024. if (m_refs > 32)
  1025. {
  1026. CLog::LogF(LOGWARNING, "The number of decoder surfaces has been limited from {} to 32.", m_refs);
  1027. m_refs = 32;
  1028. }
  1029. // Check if available video memory is sufficient for 4K decoding (is need ~3000 MB)
  1030. if (avctx->width >= 3840 && m_refs > 16 && videoMem < (LIMIT_VIDEO_MEMORY_4K * MB))
  1031. {
  1032. CLog::LogF(LOGWARNING,
  1033. "Current available video memory ({} MB) is insufficient 4K video decoding (DXVA2) "
  1034. "using {} surfaces. Decoder surfaces has been limited to 16.", videoMem / MB, m_refs);
  1035. m_refs = 16;
  1036. }
  1037. if (!OpenDecoder())
  1038. {
  1039. m_bufferPool.reset();
  1040. return false;
  1041. }
  1042. avctx->get_buffer2 = FFGetBuffer;
  1043. avctx->hwaccel_context = m_avD3D11Context;
  1044. avctx->slice_flags = SLICE_FLAG_ALLOW_FIELD | SLICE_FLAG_CODED_ORDER;
  1045. mainctx->get_buffer2 = FFGetBuffer;
  1046. mainctx->hwaccel_context = m_avD3D11Context;
  1047. mainctx->slice_flags = SLICE_FLAG_ALLOW_FIELD | SLICE_FLAG_CODED_ORDER;
  1048. m_avCtx = mainctx;
  1049. if (m_format.Guid == DXVADDI_Intel_ModeH264_E)
  1050. {
  1051. #ifdef FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO
  1052. m_avD3D11Context->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
  1053. #else
  1054. CLog::LogFunction(LOGWARNING, "DXVA", "used Intel ClearVideo decoder, but no support workaround for it in libavcodec.");
  1055. #endif
  1056. }
  1057. else if (ad.VendorId == PCIV_ATI && IsL41LimitedATI())
  1058. {
  1059. #ifdef FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG
  1060. m_avD3D11Context->workaround |= FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG;
  1061. #else
  1062. CLog::LogFunction(LOGWARNING, "DXVA", "video card with different scaling list zigzag order detected, but no support in libavcodec.");
  1063. #endif
  1064. }
  1065. std::list<EINTERLACEMETHOD> deintMethods;
  1066. deintMethods.push_back(VS_INTERLACEMETHOD_NONE);
  1067. m_processInfo.UpdateDeinterlacingMethods(deintMethods);
  1068. m_processInfo.SetDeinterlacingMethodDefault(VS_INTERLACEMETHOD_DXVA_AUTO);
  1069. m_state = DXVA_OPEN;
  1070. return true;
  1071. }
  1072. CDVDVideoCodec::VCReturn CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
  1073. {
  1074. CSingleLock lock(m_section);
  1075. const CDVDVideoCodec::VCReturn result = Check(avctx);
  1076. if (result != CDVDVideoCodec::VC_NONE)
  1077. return result;
  1078. if (frame)
  1079. {
  1080. if (m_bufferPool->IsValid(reinterpret_cast<ID3D11View*>(frame->data[3])))
  1081. {
  1082. if (m_videoBuffer)
  1083. m_videoBuffer->Release();
  1084. m_videoBuffer = reinterpret_cast<CVideoBuffer*>(m_bufferPool->Get());
  1085. if (!m_videoBuffer)
  1086. {
  1087. CLog::LogFunction(ERROR, "DXVA", "ran out of buffers.");
  1088. return CDVDVideoCodec::VC_ERROR;
  1089. }
  1090. m_videoBuffer->SetRef(frame);
  1091. m_videoBuffer->Initialize(this);
  1092. return CDVDVideoCodec::VC_PICTURE;
  1093. }
  1094. CLog::LogFunction(LOGWARNING, "DXVA", "ignoring invalid surface.");
  1095. return CDVDVideoCodec::VC_BUFFER;
  1096. }
  1097. return CDVDVideoCodec::VC_BUFFER;
  1098. }
  1099. bool CDecoder::GetPicture(AVCodecContext* avctx, VideoPicture* picture)
  1100. {
  1101. static_cast<ICallbackHWAccel*>(avctx->opaque)->GetPictureCommon(picture);
  1102. CSingleLock lock(m_section);
  1103. if (picture->videoBuffer)
  1104. picture->videoBuffer->Release();
  1105. picture->videoBuffer = m_videoBuffer;
  1106. m_videoBuffer = nullptr;
  1107. if (!m_dxvaContext->IsContextShared())
  1108. {
  1109. int queued, discard, free;
  1110. m_processInfo.GetRenderBuffers(queued, discard, free);
  1111. if (free > 1)
  1112. {
  1113. DX::Windowing()->RequestDecodingTime();
  1114. }
  1115. else
  1116. {
  1117. DX::Windowing()->ReleaseDecodingTime();
  1118. }
  1119. }
  1120. return true;
  1121. }
  1122. void CDecoder::Reset()
  1123. {
  1124. if (m_videoBuffer)
  1125. {
  1126. m_videoBuffer->Release();
  1127. m_videoBuffer = nullptr;
  1128. }
  1129. }
  1130. CDVDVideoCodec::VCReturn CDecoder::Check(AVCodecContext* avctx)
  1131. {
  1132. CSingleLock lock(m_section);
  1133. // we may not have a hw decoder on systems (AMD HD2xxx, HD3xxx) which are only capable
  1134. // of opening a single decoder and VideoPlayer opened a new stream without having flushed
  1135. // current one.
  1136. if (!m_pD3D11Decoder)
  1137. return CDVDVideoCodec::VC_BUFFER;
  1138. // reset decoder if context detects an error on its device
  1139. if (!m_dxvaContext->Check())
  1140. m_state = DXVA_RESET;
  1141. // app device is lost
  1142. if (m_state == DXVA_LOST)
  1143. {
  1144. lock.Leave();
  1145. // wait app device restoration
  1146. m_event.Wait(2000ms);
  1147. lock.Enter();
  1148. // still in lost state after 2sec
  1149. if (m_state == DXVA_LOST)
  1150. {
  1151. Close();
  1152. CLog::LogF(LOGERROR, "device didn't reset in reasonable time.");
  1153. return CDVDVideoCodec::VC_ERROR;
  1154. }
  1155. }
  1156. if (m_state != DXVA_OPEN)
  1157. {
  1158. // reset context in case of app device reset or context device error
  1159. if (!m_dxvaContext->Reset())
  1160. {
  1161. CLog::LogF(LOGERROR, "context didn't reset.");
  1162. return CDVDVideoCodec::VC_ERROR;
  1163. }
  1164. if (!Open(avctx, avctx, avctx->pix_fmt))
  1165. {
  1166. CLog::LogF(LOGERROR, "decoder was not able to reset.");
  1167. Close();
  1168. return CDVDVideoCodec::VC_ERROR;
  1169. }
  1170. // decoder re-opened
  1171. m_state = DXVA_OPEN;
  1172. return CDVDVideoCodec::VC_FLUSHED;
  1173. }
  1174. if (avctx->refs > m_refs)
  1175. {
  1176. CLog::LogF(LOGWARNING, "number of required reference frames increased, recreating decoder.");
  1177. Close();
  1178. return CDVDVideoCodec::VC_FLUSHED;
  1179. }
  1180. // Status reports are available only for the DXVA2_ModeH264 and DXVA2_ModeVC1 modes
  1181. if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_VC1 &&
  1182. avctx->codec_id != AV_CODEC_ID_WMV3)
  1183. return CDVDVideoCodec::VC_NONE;
  1184. #ifdef TARGET_WINDOWS_DESKTOP
  1185. D3D11_VIDEO_DECODER_EXTENSION data = {};
  1186. union {
  1187. DXVA_Status_H264 h264;
  1188. DXVA_Status_VC1 vc1;
  1189. } status = {};
  1190. /* I'm not sure, but MSDN says nothing about extensions functions in D3D11, try to using with same way as in DX9 */
  1191. data.Function = DXVA_STATUS_REPORTING_FUNCTION;
  1192. data.pPrivateOutputData = &status;
  1193. data.PrivateOutputDataSize = avctx->codec_id == AV_CODEC_ID_H264 ? sizeof(DXVA_Status_H264) : sizeof(DXVA_Status_VC1);
  1194. HRESULT hr;
  1195. if (FAILED(hr = m_pD3D11Context->DecoderExtension(m_pD3D11Decoder.Get(), &data)))
  1196. {
  1197. CLog::LogFunction(LOGWARNING, "DXVA", "failed to get decoder status - {:#08X}.", hr);
  1198. return CDVDVideoCodec::VC_ERROR;
  1199. }
  1200. if (avctx->codec_id == AV_CODEC_ID_H264)
  1201. {
  1202. if (status.h264.bStatus)
  1203. CLog::LogFunction(LOGWARNING, "DXVA", "decoder problem of status {} with {}.",
  1204. status.h264.bStatus, status.h264.bBufType);
  1205. }
  1206. else
  1207. {
  1208. if (status.vc1.bStatus)
  1209. CLog::LogFunction(LOGWARNING, "DXVA", "decoder problem of status {} with {}.",
  1210. status.vc1.bStatus, status.vc1.bBufType);
  1211. }
  1212. #endif
  1213. return CDVDVideoCodec::VC_NONE;
  1214. }
  1215. bool CDecoder::OpenDecoder()
  1216. {
  1217. m_pD3D11Decoder = nullptr;
  1218. m_pD3D11Context = nullptr;
  1219. m_avD3D11Context->decoder = nullptr;
  1220. m_avD3D11Context->video_context = nullptr;
  1221. m_avD3D11Context->surface_count = m_refs;
  1222. DXGI_ADAPTER_DESC AIdentifier = {};
  1223. DX::DeviceResources::Get()->GetAdapterDesc(&AIdentifier);
  1224. // use true shared buffers on Intel
  1225. bool trueShared = m_dxvaContext->IsContextShared() && AIdentifier.VendorId == PCIV_Intel;
  1226. if (!m_dxvaContext->CreateSurfaces(m_format, m_avD3D11Context->surface_count, m_surface_alignment,
  1227. m_avD3D11Context->surface, &m_sharedHandle, trueShared))
  1228. return false;
  1229. if (!m_dxvaContext->CreateDecoder(m_format, *m_avD3D11Context->cfg, m_pD3D11Decoder.GetAddressOf(),
  1230. m_pD3D11Context.GetAddressOf()))
  1231. return false;
  1232. if (m_dxvaContext->IsContextShared())
  1233. {
  1234. if (trueShared)
  1235. m_bufferPool = std::make_shared<CVideoBufferPoolTyped<CVideoBufferShared>>();
  1236. else
  1237. m_bufferPool = std::make_shared<CVideoBufferPoolTyped<CVideoBufferCopy>>();
  1238. }
  1239. else
  1240. m_bufferPool = std::make_shared<CVideoBufferPoolTyped<CVideoBuffer>>();
  1241. for (unsigned i = 0; i < m_avD3D11Context->surface_count; i++)
  1242. m_bufferPool->AddView(m_avD3D11Context->surface[i]);
  1243. m_avD3D11Context->decoder = m_pD3D11Decoder.Get();
  1244. m_avD3D11Context->video_context = m_pD3D11Context.Get();
  1245. return true;
  1246. }
  1247. bool CDecoder::Supports(enum AVPixelFormat fmt)
  1248. {
  1249. return fmt == AV_PIX_FMT_D3D11VA_VLD;
  1250. }
  1251. void CDecoder::FFReleaseBuffer(void* opaque, uint8_t* data)
  1252. {
  1253. auto decoder = static_cast<CDecoder*>(opaque);
  1254. decoder->ReleaseBuffer(data);
  1255. }
  1256. void CDecoder::ReleaseBuffer(uint8_t* data)
  1257. {
  1258. const auto view = reinterpret_cast<ID3D11VideoDecoderOutputView*>(data);
  1259. if (!m_bufferPool->ReturnView(view))
  1260. {
  1261. CLog::LogF(LOGWARNING, "return of invalid surface.");
  1262. }
  1263. IHardwareDecoder::Release();
  1264. }
  1265. int CDecoder::FFGetBuffer(AVCodecContext* avctx, AVFrame* pic, int flags)
  1266. {
  1267. auto* cb = static_cast<ICallbackHWAccel*>(avctx->opaque);
  1268. auto decoder = dynamic_cast<CDecoder*>(cb->GetHWAccel());
  1269. return decoder->GetBuffer(avctx, pic);
  1270. }
  1271. int CDecoder::GetBuffer(AVCodecContext* avctx, AVFrame* pic)
  1272. {
  1273. if (!m_pD3D11Decoder)
  1274. return -1;
  1275. ID3D11View* view = m_bufferPool->GetView();
  1276. if (view == nullptr)
  1277. {
  1278. CLog::LogF(LOGERROR, "no surface available.");
  1279. m_state = DXVA_RESET;
  1280. return -1;
  1281. }
  1282. pic->reordered_opaque = avctx->reordered_opaque;
  1283. for (unsigned i = 0; i < 4; i++)
  1284. {
  1285. pic->data[i] = nullptr;
  1286. pic->linesize[i] = 0;
  1287. }
  1288. pic->data[0] = reinterpret_cast<uint8_t*>(view);
  1289. pic->data[3] = reinterpret_cast<uint8_t*>(view);
  1290. AVBufferRef* buffer = av_buffer_create(pic->data[3], 0, CDecoder::FFReleaseBuffer, this, 0);
  1291. if (!buffer)
  1292. {
  1293. CLog::LogF(LOGERROR, "error creating buffer.");
  1294. return -1;
  1295. }
  1296. pic->buf[0] = buffer;
  1297. Acquire();
  1298. return 0;
  1299. }