common_directx9.cpp 12 KB

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