common_directx9.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. #include "common_directx9.h"
  2. #include "device_directx9.h"
  3. #include <objbase.h>
  4. #include <initguid.h>
  5. #include <d3d9.h>
  6. #include <map>
  7. #include <atlbase.h>
  8. #define D3DFMT_NV12 (D3DFORMAT) MAKEFOURCC('N', 'V', '1', '2')
  9. #define D3DFMT_YV12 (D3DFORMAT) MAKEFOURCC('Y', 'V', '1', '2')
  10. #define D3DFMT_P010 (D3DFORMAT) MAKEFOURCC('P', '0', '1', '0')
  11. #define MSDK_SAFE_FREE(X) \
  12. { \
  13. if (X) { \
  14. free(X); \
  15. X = NULL; \
  16. } \
  17. }
  18. std::map<mfxMemId *, mfxHDL> dx9_allocResponses;
  19. std::map<mfxHDL, mfxFrameAllocResponse> dx9_allocDecodeResponses;
  20. std::map<mfxHDL, int> dx9_allocDecodeRefCount;
  21. CComPtr<IDirect3DDeviceManager9> m_manager;
  22. CComPtr<IDirectXVideoDecoderService> m_decoderService;
  23. CComPtr<IDirectXVideoProcessorService> m_processorService;
  24. HANDLE m_hDecoder;
  25. HANDLE m_hProcessor;
  26. DWORD m_surfaceUsage;
  27. CD3D9Device *g_hwdevice;
  28. const struct {
  29. mfxIMPL impl; // actual implementation
  30. mfxU32 adapterID; // device adapter number
  31. } implTypes[] = {{MFX_IMPL_HARDWARE, 0},
  32. {MFX_IMPL_HARDWARE2, 1},
  33. {MFX_IMPL_HARDWARE3, 2},
  34. {MFX_IMPL_HARDWARE4, 3}};
  35. struct mfxAllocatorParams {
  36. virtual ~mfxAllocatorParams(){};
  37. };
  38. struct D3DAllocatorParams : mfxAllocatorParams {
  39. IDirect3DDeviceManager9 *pManager;
  40. DWORD surfaceUsage;
  41. D3DAllocatorParams() : pManager(), surfaceUsage() {}
  42. };
  43. mfxStatus DX9_Alloc_Init(D3DAllocatorParams *pParams)
  44. {
  45. D3DAllocatorParams *pd3dParams = 0;
  46. pd3dParams = dynamic_cast<D3DAllocatorParams *>(pParams);
  47. if (!pd3dParams)
  48. return MFX_ERR_NOT_INITIALIZED;
  49. m_manager = pd3dParams->pManager;
  50. m_surfaceUsage = pd3dParams->surfaceUsage;
  51. return MFX_ERR_NONE;
  52. }
  53. mfxStatus DX9_CreateHWDevice(mfxSession session, mfxHDL *deviceHandle, HWND,
  54. bool)
  55. {
  56. mfxStatus result;
  57. g_hwdevice = new CD3D9Device;
  58. mfxU32 adapterNum = 0;
  59. mfxIMPL impl;
  60. MFXQueryIMPL(session, &impl);
  61. mfxIMPL baseImpl = MFX_IMPL_BASETYPE(
  62. impl); // Extract Media SDK base implementation type
  63. // get corresponding adapter number
  64. for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(implTypes[0]); i++) {
  65. if (implTypes[i].impl == baseImpl) {
  66. adapterNum = implTypes[i].adapterID;
  67. break;
  68. }
  69. }
  70. POINT point = {0, 0};
  71. HWND window = WindowFromPoint(point);
  72. result = g_hwdevice->Init(window, 0, adapterNum);
  73. if (result != MFX_ERR_NONE) {
  74. return result;
  75. }
  76. g_hwdevice->GetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, deviceHandle);
  77. D3DAllocatorParams dx9_allocParam;
  78. dx9_allocParam.pManager =
  79. reinterpret_cast<IDirect3DDeviceManager9 *>(*deviceHandle);
  80. DX9_Alloc_Init(&dx9_allocParam);
  81. return MFX_ERR_NONE;
  82. }
  83. void DX9_CleanupHWDevice()
  84. {
  85. if (g_hwdevice) {
  86. // g_hwdevice->Close();
  87. delete g_hwdevice;
  88. g_hwdevice = NULL;
  89. }
  90. if (m_manager && m_hDecoder) {
  91. m_manager->CloseDeviceHandle(m_hDecoder);
  92. m_manager = NULL;
  93. m_hDecoder = NULL;
  94. }
  95. if (m_manager && m_hProcessor) {
  96. m_manager->CloseDeviceHandle(m_hProcessor);
  97. m_manager = NULL;
  98. m_hProcessor = NULL;
  99. }
  100. if (m_decoderService) {
  101. // delete m_decoderService;
  102. m_decoderService = NULL;
  103. }
  104. if (m_processorService) {
  105. // delete m_processorService;
  106. m_processorService = NULL;
  107. }
  108. }
  109. D3DFORMAT ConvertMfxFourccToD3dFormat(mfxU32 fourcc)
  110. {
  111. switch (fourcc) {
  112. case MFX_FOURCC_NV12:
  113. return D3DFMT_NV12;
  114. case MFX_FOURCC_YV12:
  115. return D3DFMT_YV12;
  116. case MFX_FOURCC_YUY2:
  117. return D3DFMT_YUY2;
  118. case MFX_FOURCC_RGB3:
  119. return D3DFMT_R8G8B8;
  120. case MFX_FOURCC_RGB4:
  121. return D3DFMT_A8R8G8B8;
  122. case MFX_FOURCC_P8:
  123. return D3DFMT_P8;
  124. case MFX_FOURCC_P010:
  125. return D3DFMT_P010;
  126. case MFX_FOURCC_A2RGB10:
  127. return D3DFMT_A2R10G10B10;
  128. default:
  129. return D3DFMT_UNKNOWN;
  130. }
  131. }
  132. mfxStatus dx9_simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
  133. {
  134. pthis; // To suppress warning for this unused parameter
  135. if (!ptr || !mid)
  136. return MFX_ERR_NULL_PTR;
  137. mfxHDLPair *dxmid = (mfxHDLPair *)mid;
  138. IDirect3DSurface9 *pSurface =
  139. static_cast<IDirect3DSurface9 *>(dxmid->first);
  140. if (pSurface == 0)
  141. return MFX_ERR_INVALID_HANDLE;
  142. D3DSURFACE_DESC desc;
  143. HRESULT hr = pSurface->GetDesc(&desc);
  144. if (FAILED(hr))
  145. return MFX_ERR_LOCK_MEMORY;
  146. if (desc.Format != D3DFMT_NV12 && desc.Format != D3DFMT_YV12 &&
  147. desc.Format != D3DFMT_YUY2 && desc.Format != D3DFMT_R8G8B8 &&
  148. desc.Format != D3DFMT_A8R8G8B8 && desc.Format != D3DFMT_P8 &&
  149. desc.Format != D3DFMT_P010 && desc.Format != D3DFMT_A2R10G10B10)
  150. return MFX_ERR_LOCK_MEMORY;
  151. D3DLOCKED_RECT locked;
  152. hr = pSurface->LockRect(&locked, 0, D3DLOCK_NOSYSLOCK);
  153. if (FAILED(hr))
  154. return MFX_ERR_LOCK_MEMORY;
  155. switch ((DWORD)desc.Format) {
  156. case D3DFMT_NV12:
  157. ptr->Pitch = (mfxU16)locked.Pitch;
  158. ptr->Y = (mfxU8 *)locked.pBits;
  159. ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
  160. ptr->V = ptr->U + 1;
  161. break;
  162. case D3DFMT_YV12:
  163. ptr->Pitch = (mfxU16)locked.Pitch;
  164. ptr->Y = (mfxU8 *)locked.pBits;
  165. ptr->V = ptr->Y + desc.Height * locked.Pitch;
  166. ptr->U = ptr->V + (desc.Height * locked.Pitch) / 4;
  167. break;
  168. case D3DFMT_YUY2:
  169. ptr->Pitch = (mfxU16)locked.Pitch;
  170. ptr->Y = (mfxU8 *)locked.pBits;
  171. ptr->U = ptr->Y + 1;
  172. ptr->V = ptr->Y + 3;
  173. break;
  174. case D3DFMT_R8G8B8:
  175. ptr->Pitch = (mfxU16)locked.Pitch;
  176. ptr->B = (mfxU8 *)locked.pBits;
  177. ptr->G = ptr->B + 1;
  178. ptr->R = ptr->B + 2;
  179. break;
  180. case D3DFMT_A8R8G8B8:
  181. case D3DFMT_A2R10G10B10:
  182. ptr->Pitch = (mfxU16)locked.Pitch;
  183. ptr->B = (mfxU8 *)locked.pBits;
  184. ptr->G = ptr->B + 1;
  185. ptr->R = ptr->B + 2;
  186. ptr->A = ptr->B + 3;
  187. break;
  188. case D3DFMT_P8:
  189. ptr->Pitch = (mfxU16)locked.Pitch;
  190. ptr->Y = (mfxU8 *)locked.pBits;
  191. ptr->U = 0;
  192. ptr->V = 0;
  193. break;
  194. case D3DFMT_P010:
  195. ptr->PitchHigh = (mfxU16)(locked.Pitch / (1 << 16));
  196. ptr->PitchLow = (mfxU16)(locked.Pitch % (1 << 16));
  197. ptr->Y = (mfxU8 *)locked.pBits;
  198. ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
  199. ptr->V = ptr->U + 1;
  200. break;
  201. }
  202. return MFX_ERR_NONE;
  203. }
  204. mfxStatus dx9_simple_unlock(mfxHDL, mfxMemId mid, mfxFrameData *ptr)
  205. {
  206. if (!mid)
  207. return MFX_ERR_NULL_PTR;
  208. mfxHDLPair *dxmid = (mfxHDLPair *)mid;
  209. IDirect3DSurface9 *pSurface =
  210. static_cast<IDirect3DSurface9 *>(dxmid->first);
  211. if (pSurface == 0)
  212. return MFX_ERR_INVALID_HANDLE;
  213. pSurface->UnlockRect();
  214. if (NULL != ptr) {
  215. ptr->Pitch = 0;
  216. ptr->Y = 0;
  217. ptr->U = 0;
  218. ptr->V = 0;
  219. }
  220. return MFX_ERR_NONE;
  221. }
  222. mfxStatus dx9_simple_gethdl(mfxHDL, mfxMemId mid, mfxHDL *handle)
  223. {
  224. if (!mid || !handle)
  225. return MFX_ERR_NULL_PTR;
  226. mfxHDLPair *dxMid = (mfxHDLPair *)mid;
  227. *handle = dxMid->first;
  228. return MFX_ERR_NONE;
  229. }
  230. mfxStatus _dx9_simple_free(mfxFrameAllocResponse *response)
  231. {
  232. if (!response)
  233. return MFX_ERR_NULL_PTR;
  234. mfxStatus sts = MFX_ERR_NONE;
  235. if (response->mids) {
  236. for (mfxU32 i = 0; i < response->NumFrameActual; i++) {
  237. if (response->mids[i]) {
  238. mfxHDLPair *dxMids =
  239. (mfxHDLPair *)response->mids[i];
  240. static_cast<IDirect3DSurface9 *>(dxMids->first)
  241. ->Release();
  242. }
  243. }
  244. MSDK_SAFE_FREE(response->mids[0]);
  245. }
  246. MSDK_SAFE_FREE(response->mids);
  247. return sts;
  248. }
  249. mfxStatus dx9_simple_free(mfxHDL pthis, mfxFrameAllocResponse *response)
  250. {
  251. if (NULL == response)
  252. return MFX_ERR_NULL_PTR;
  253. if (dx9_allocResponses.find(response->mids) ==
  254. dx9_allocResponses.end()) {
  255. // Decode free response handling
  256. if (--dx9_allocDecodeRefCount[pthis] == 0) {
  257. _dx9_simple_free(response);
  258. dx9_allocDecodeResponses.erase(pthis);
  259. dx9_allocDecodeRefCount.erase(pthis);
  260. }
  261. } else {
  262. // Encode and VPP free response handling
  263. dx9_allocResponses.erase(response->mids);
  264. _dx9_simple_free(response);
  265. }
  266. return MFX_ERR_NONE;
  267. }
  268. mfxStatus _dx9_simple_alloc(mfxFrameAllocRequest *request,
  269. mfxFrameAllocResponse *response)
  270. {
  271. HRESULT hr;
  272. MSDK_CHECK_POINTER(request, MFX_ERR_NULL_PTR);
  273. if (request->NumFrameSuggested == 0)
  274. return MFX_ERR_UNKNOWN;
  275. D3DFORMAT format = ConvertMfxFourccToD3dFormat(request->Info.FourCC);
  276. if (format == D3DFMT_UNKNOWN)
  277. return MFX_ERR_UNSUPPORTED;
  278. DWORD target;
  279. if (MFX_MEMTYPE_DXVA2_DECODER_TARGET & request->Type) {
  280. target = DXVA2_VideoDecoderRenderTarget;
  281. } else if (MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET & request->Type) {
  282. target = DXVA2_VideoProcessorRenderTarget;
  283. } else
  284. return MFX_ERR_UNSUPPORTED;
  285. IDirectXVideoAccelerationService *videoService = NULL;
  286. if (target == DXVA2_VideoProcessorRenderTarget) {
  287. if (!m_hProcessor) {
  288. hr = m_manager->OpenDeviceHandle(&m_hProcessor);
  289. if (FAILED(hr))
  290. return MFX_ERR_MEMORY_ALLOC;
  291. hr = m_manager->GetVideoService(
  292. m_hProcessor, IID_IDirectXVideoProcessorService,
  293. (void **)&m_processorService);
  294. if (FAILED(hr))
  295. return MFX_ERR_MEMORY_ALLOC;
  296. }
  297. videoService = m_processorService;
  298. } else {
  299. if (!m_hDecoder) {
  300. hr = m_manager->OpenDeviceHandle(&m_hDecoder);
  301. if (FAILED(hr))
  302. return MFX_ERR_MEMORY_ALLOC;
  303. hr = m_manager->GetVideoService(
  304. m_hDecoder, IID_IDirectXVideoDecoderService,
  305. (void **)&m_decoderService);
  306. if (FAILED(hr))
  307. return MFX_ERR_MEMORY_ALLOC;
  308. }
  309. videoService = m_decoderService;
  310. }
  311. mfxHDLPair *dxMids = NULL, **dxMidPtrs = NULL;
  312. dxMids = (mfxHDLPair *)calloc(request->NumFrameSuggested,
  313. sizeof(mfxHDLPair));
  314. dxMidPtrs = (mfxHDLPair **)calloc(request->NumFrameSuggested,
  315. sizeof(mfxHDLPair *));
  316. if (!dxMids || !dxMidPtrs) {
  317. MSDK_SAFE_FREE(dxMids);
  318. MSDK_SAFE_FREE(dxMidPtrs);
  319. return MFX_ERR_MEMORY_ALLOC;
  320. }
  321. response->mids = (mfxMemId *)dxMidPtrs;
  322. response->NumFrameActual = request->NumFrameSuggested;
  323. if (request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
  324. for (int i = 0; i < request->NumFrameSuggested; i++) {
  325. hr = videoService->CreateSurface(
  326. request->Info.Width, request->Info.Height, 0,
  327. format, D3DPOOL_DEFAULT, m_surfaceUsage, target,
  328. (IDirect3DSurface9 **)&dxMids[i].first,
  329. &dxMids[i].second);
  330. if (FAILED(hr)) {
  331. _dx9_simple_free(response);
  332. MSDK_SAFE_FREE(dxMids);
  333. MSDK_SAFE_FREE(dxMidPtrs);
  334. return MFX_ERR_MEMORY_ALLOC;
  335. }
  336. dxMidPtrs[i] = &dxMids[i];
  337. }
  338. } else {
  339. safe_array<IDirect3DSurface9 *> dxSrf(
  340. new IDirect3DSurface9 *[request->NumFrameSuggested]);
  341. if (!dxSrf.get()) {
  342. MSDK_SAFE_FREE(dxMids);
  343. MSDK_SAFE_FREE(dxMidPtrs);
  344. return MFX_ERR_MEMORY_ALLOC;
  345. }
  346. hr = videoService->CreateSurface(
  347. request->Info.Width, request->Info.Height,
  348. request->NumFrameSuggested - 1, format, D3DPOOL_DEFAULT,
  349. m_surfaceUsage, target, dxSrf.get(), NULL);
  350. if (FAILED(hr)) {
  351. MSDK_SAFE_FREE(dxMids);
  352. MSDK_SAFE_FREE(dxMidPtrs);
  353. return MFX_ERR_MEMORY_ALLOC;
  354. }
  355. for (int i = 0; i < request->NumFrameSuggested; i++) {
  356. dxMids[i].first = dxSrf.get()[i];
  357. dxMidPtrs[i] = &dxMids[i];
  358. }
  359. }
  360. return MFX_ERR_NONE;
  361. }
  362. mfxStatus dx9_simple_alloc(mfxHDL pthis, mfxFrameAllocRequest *request,
  363. mfxFrameAllocResponse *response)
  364. {
  365. mfxStatus sts = MFX_ERR_NONE;
  366. if (request->Type & MFX_MEMTYPE_SYSTEM_MEMORY)
  367. return MFX_ERR_UNSUPPORTED;
  368. if (dx9_allocDecodeResponses.find(pthis) !=
  369. dx9_allocDecodeResponses.end() &&
  370. MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
  371. MFX_MEMTYPE_FROM_DECODE & request->Type) {
  372. // Memory for this request was already allocated during manual allocation stage. Return saved response
  373. // When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed.
  374. // Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response
  375. // (No such restriction applies to Encode or VPP)
  376. *response = dx9_allocDecodeResponses[pthis];
  377. dx9_allocDecodeRefCount[pthis]++;
  378. } else {
  379. sts = _dx9_simple_alloc(request, response);
  380. if (MFX_ERR_NONE == sts) {
  381. if (MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
  382. MFX_MEMTYPE_FROM_DECODE & request->Type) {
  383. // Decode alloc response handling
  384. dx9_allocDecodeResponses[pthis] = *response;
  385. dx9_allocDecodeRefCount[pthis]++;
  386. } else {
  387. // Encode and VPP alloc response handling
  388. dx9_allocResponses[response->mids] = pthis;
  389. }
  390. }
  391. }
  392. return sts;
  393. }