| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- #include "common_directx9.h"
- #include "device_directx9.h"
- #include <objbase.h>
- #include <initguid.h>
- #include <d3d9.h>
- #include <map>
- #include <atlbase.h>
- #define D3DFMT_NV12 (D3DFORMAT) MAKEFOURCC('N', 'V', '1', '2')
- #define D3DFMT_YV12 (D3DFORMAT) MAKEFOURCC('Y', 'V', '1', '2')
- #define D3DFMT_P010 (D3DFORMAT) MAKEFOURCC('P', '0', '1', '0')
- #define MSDK_SAFE_FREE(X) \
- { \
- if (X) { \
- free(X); \
- X = NULL; \
- } \
- }
- std::map<mfxMemId *, mfxHDL> dx9_allocResponses;
- std::map<mfxHDL, mfxFrameAllocResponse> dx9_allocDecodeResponses;
- std::map<mfxHDL, int> dx9_allocDecodeRefCount;
- CComPtr<IDirect3DDeviceManager9> m_manager;
- CComPtr<IDirectXVideoDecoderService> m_decoderService;
- CComPtr<IDirectXVideoProcessorService> m_processorService;
- HANDLE m_hDecoder;
- HANDLE m_hProcessor;
- DWORD m_surfaceUsage;
- CD3D9Device *g_hwdevice;
- const struct {
- mfxIMPL impl; // actual implementation
- mfxU32 adapterID; // device adapter number
- } implTypes[] = {{MFX_IMPL_HARDWARE, 0},
- {MFX_IMPL_HARDWARE2, 1},
- {MFX_IMPL_HARDWARE3, 2},
- {MFX_IMPL_HARDWARE4, 3}};
- struct mfxAllocatorParams {
- virtual ~mfxAllocatorParams(){};
- };
- struct D3DAllocatorParams : mfxAllocatorParams {
- IDirect3DDeviceManager9 *pManager;
- DWORD surfaceUsage;
- D3DAllocatorParams() : pManager(), surfaceUsage() {}
- };
- mfxStatus DX9_Alloc_Init(D3DAllocatorParams *pParams)
- {
- D3DAllocatorParams *pd3dParams = 0;
- pd3dParams = dynamic_cast<D3DAllocatorParams *>(pParams);
- if (!pd3dParams)
- return MFX_ERR_NOT_INITIALIZED;
- m_manager = pd3dParams->pManager;
- m_surfaceUsage = pd3dParams->surfaceUsage;
- return MFX_ERR_NONE;
- }
- mfxStatus DX9_CreateHWDevice(mfxSession session, mfxHDL *deviceHandle, HWND,
- bool)
- {
- mfxStatus result;
- g_hwdevice = new CD3D9Device;
- mfxU32 adapterNum = 0;
- mfxIMPL impl;
- MFXQueryIMPL(session, &impl);
- mfxIMPL baseImpl = MFX_IMPL_BASETYPE(
- impl); // Extract Media SDK base implementation type
- // get corresponding adapter number
- for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(implTypes[0]); i++) {
- if (implTypes[i].impl == baseImpl) {
- adapterNum = implTypes[i].adapterID;
- break;
- }
- }
- POINT point = {0, 0};
- HWND window = WindowFromPoint(point);
- result = g_hwdevice->Init(window, 0, adapterNum);
- if (result != MFX_ERR_NONE) {
- return result;
- }
- g_hwdevice->GetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, deviceHandle);
- D3DAllocatorParams dx9_allocParam;
- dx9_allocParam.pManager =
- reinterpret_cast<IDirect3DDeviceManager9 *>(*deviceHandle);
- DX9_Alloc_Init(&dx9_allocParam);
- return MFX_ERR_NONE;
- }
- void DX9_CleanupHWDevice()
- {
- if (g_hwdevice) {
- // g_hwdevice->Close();
- delete g_hwdevice;
- g_hwdevice = NULL;
- }
- if (m_manager && m_hDecoder) {
- m_manager->CloseDeviceHandle(m_hDecoder);
- m_manager = NULL;
- m_hDecoder = NULL;
- }
- if (m_manager && m_hProcessor) {
- m_manager->CloseDeviceHandle(m_hProcessor);
- m_manager = NULL;
- m_hProcessor = NULL;
- }
- if (m_decoderService) {
- // delete m_decoderService;
- m_decoderService = NULL;
- }
- if (m_processorService) {
- // delete m_processorService;
- m_processorService = NULL;
- }
- }
- D3DFORMAT ConvertMfxFourccToD3dFormat(mfxU32 fourcc)
- {
- switch (fourcc) {
- case MFX_FOURCC_NV12:
- return D3DFMT_NV12;
- case MFX_FOURCC_YV12:
- return D3DFMT_YV12;
- case MFX_FOURCC_YUY2:
- return D3DFMT_YUY2;
- case MFX_FOURCC_RGB3:
- return D3DFMT_R8G8B8;
- case MFX_FOURCC_RGB4:
- return D3DFMT_A8R8G8B8;
- case MFX_FOURCC_P8:
- return D3DFMT_P8;
- case MFX_FOURCC_P010:
- return D3DFMT_P010;
- case MFX_FOURCC_A2RGB10:
- return D3DFMT_A2R10G10B10;
- default:
- return D3DFMT_UNKNOWN;
- }
- }
- mfxStatus dx9_simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
- {
- pthis; // To suppress warning for this unused parameter
- if (!ptr || !mid)
- return MFX_ERR_NULL_PTR;
- mfxHDLPair *dxmid = (mfxHDLPair *)mid;
- IDirect3DSurface9 *pSurface =
- static_cast<IDirect3DSurface9 *>(dxmid->first);
- if (pSurface == 0)
- return MFX_ERR_INVALID_HANDLE;
- D3DSURFACE_DESC desc;
- HRESULT hr = pSurface->GetDesc(&desc);
- if (FAILED(hr))
- return MFX_ERR_LOCK_MEMORY;
- if (desc.Format != D3DFMT_NV12 && desc.Format != D3DFMT_YV12 &&
- desc.Format != D3DFMT_YUY2 && desc.Format != D3DFMT_R8G8B8 &&
- desc.Format != D3DFMT_A8R8G8B8 && desc.Format != D3DFMT_P8 &&
- desc.Format != D3DFMT_P010 && desc.Format != D3DFMT_A2R10G10B10)
- return MFX_ERR_LOCK_MEMORY;
- D3DLOCKED_RECT locked;
- hr = pSurface->LockRect(&locked, 0, D3DLOCK_NOSYSLOCK);
- if (FAILED(hr))
- return MFX_ERR_LOCK_MEMORY;
- switch ((DWORD)desc.Format) {
- case D3DFMT_NV12:
- ptr->Pitch = (mfxU16)locked.Pitch;
- ptr->Y = (mfxU8 *)locked.pBits;
- ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
- ptr->V = ptr->U + 1;
- break;
- case D3DFMT_YV12:
- ptr->Pitch = (mfxU16)locked.Pitch;
- ptr->Y = (mfxU8 *)locked.pBits;
- ptr->V = ptr->Y + desc.Height * locked.Pitch;
- ptr->U = ptr->V + (desc.Height * locked.Pitch) / 4;
- break;
- case D3DFMT_YUY2:
- ptr->Pitch = (mfxU16)locked.Pitch;
- ptr->Y = (mfxU8 *)locked.pBits;
- ptr->U = ptr->Y + 1;
- ptr->V = ptr->Y + 3;
- break;
- case D3DFMT_R8G8B8:
- ptr->Pitch = (mfxU16)locked.Pitch;
- ptr->B = (mfxU8 *)locked.pBits;
- ptr->G = ptr->B + 1;
- ptr->R = ptr->B + 2;
- break;
- case D3DFMT_A8R8G8B8:
- case D3DFMT_A2R10G10B10:
- ptr->Pitch = (mfxU16)locked.Pitch;
- ptr->B = (mfxU8 *)locked.pBits;
- ptr->G = ptr->B + 1;
- ptr->R = ptr->B + 2;
- ptr->A = ptr->B + 3;
- break;
- case D3DFMT_P8:
- ptr->Pitch = (mfxU16)locked.Pitch;
- ptr->Y = (mfxU8 *)locked.pBits;
- ptr->U = 0;
- ptr->V = 0;
- break;
- case D3DFMT_P010:
- ptr->PitchHigh = (mfxU16)(locked.Pitch / (1 << 16));
- ptr->PitchLow = (mfxU16)(locked.Pitch % (1 << 16));
- ptr->Y = (mfxU8 *)locked.pBits;
- ptr->U = (mfxU8 *)locked.pBits + desc.Height * locked.Pitch;
- ptr->V = ptr->U + 1;
- break;
- }
- return MFX_ERR_NONE;
- }
- mfxStatus dx9_simple_unlock(mfxHDL, mfxMemId mid, mfxFrameData *ptr)
- {
- if (!mid)
- return MFX_ERR_NULL_PTR;
- mfxHDLPair *dxmid = (mfxHDLPair *)mid;
- IDirect3DSurface9 *pSurface =
- static_cast<IDirect3DSurface9 *>(dxmid->first);
- if (pSurface == 0)
- return MFX_ERR_INVALID_HANDLE;
- pSurface->UnlockRect();
- if (NULL != ptr) {
- ptr->Pitch = 0;
- ptr->Y = 0;
- ptr->U = 0;
- ptr->V = 0;
- }
- return MFX_ERR_NONE;
- }
- mfxStatus dx9_simple_gethdl(mfxHDL, mfxMemId mid, mfxHDL *handle)
- {
- if (!mid || !handle)
- return MFX_ERR_NULL_PTR;
- mfxHDLPair *dxMid = (mfxHDLPair *)mid;
- *handle = dxMid->first;
- return MFX_ERR_NONE;
- }
- mfxStatus _dx9_simple_free(mfxFrameAllocResponse *response)
- {
- if (!response)
- return MFX_ERR_NULL_PTR;
- mfxStatus sts = MFX_ERR_NONE;
- if (response->mids) {
- for (mfxU32 i = 0; i < response->NumFrameActual; i++) {
- if (response->mids[i]) {
- mfxHDLPair *dxMids =
- (mfxHDLPair *)response->mids[i];
- static_cast<IDirect3DSurface9 *>(dxMids->first)
- ->Release();
- }
- }
- MSDK_SAFE_FREE(response->mids[0]);
- }
- MSDK_SAFE_FREE(response->mids);
- return sts;
- }
- mfxStatus dx9_simple_free(mfxHDL pthis, mfxFrameAllocResponse *response)
- {
- if (NULL == response)
- return MFX_ERR_NULL_PTR;
- if (dx9_allocResponses.find(response->mids) ==
- dx9_allocResponses.end()) {
- // Decode free response handling
- if (--dx9_allocDecodeRefCount[pthis] == 0) {
- _dx9_simple_free(response);
- dx9_allocDecodeResponses.erase(pthis);
- dx9_allocDecodeRefCount.erase(pthis);
- }
- } else {
- // Encode and VPP free response handling
- dx9_allocResponses.erase(response->mids);
- _dx9_simple_free(response);
- }
- return MFX_ERR_NONE;
- }
- mfxStatus _dx9_simple_alloc(mfxFrameAllocRequest *request,
- mfxFrameAllocResponse *response)
- {
- HRESULT hr;
- MSDK_CHECK_POINTER(request, MFX_ERR_NULL_PTR);
- if (request->NumFrameSuggested == 0)
- return MFX_ERR_UNKNOWN;
- D3DFORMAT format = ConvertMfxFourccToD3dFormat(request->Info.FourCC);
- if (format == D3DFMT_UNKNOWN)
- return MFX_ERR_UNSUPPORTED;
- DWORD target;
- if (MFX_MEMTYPE_DXVA2_DECODER_TARGET & request->Type) {
- target = DXVA2_VideoDecoderRenderTarget;
- } else if (MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET & request->Type) {
- target = DXVA2_VideoProcessorRenderTarget;
- } else
- return MFX_ERR_UNSUPPORTED;
- IDirectXVideoAccelerationService *videoService = NULL;
- if (target == DXVA2_VideoProcessorRenderTarget) {
- if (!m_hProcessor) {
- hr = m_manager->OpenDeviceHandle(&m_hProcessor);
- if (FAILED(hr))
- return MFX_ERR_MEMORY_ALLOC;
- hr = m_manager->GetVideoService(
- m_hProcessor, IID_IDirectXVideoProcessorService,
- (void **)&m_processorService);
- if (FAILED(hr))
- return MFX_ERR_MEMORY_ALLOC;
- }
- videoService = m_processorService;
- } else {
- if (!m_hDecoder) {
- hr = m_manager->OpenDeviceHandle(&m_hDecoder);
- if (FAILED(hr))
- return MFX_ERR_MEMORY_ALLOC;
- hr = m_manager->GetVideoService(
- m_hDecoder, IID_IDirectXVideoDecoderService,
- (void **)&m_decoderService);
- if (FAILED(hr))
- return MFX_ERR_MEMORY_ALLOC;
- }
- videoService = m_decoderService;
- }
- mfxHDLPair *dxMids = NULL, **dxMidPtrs = NULL;
- dxMids = (mfxHDLPair *)calloc(request->NumFrameSuggested,
- sizeof(mfxHDLPair));
- dxMidPtrs = (mfxHDLPair **)calloc(request->NumFrameSuggested,
- sizeof(mfxHDLPair *));
- if (!dxMids || !dxMidPtrs) {
- MSDK_SAFE_FREE(dxMids);
- MSDK_SAFE_FREE(dxMidPtrs);
- return MFX_ERR_MEMORY_ALLOC;
- }
- response->mids = (mfxMemId *)dxMidPtrs;
- response->NumFrameActual = request->NumFrameSuggested;
- if (request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
- for (int i = 0; i < request->NumFrameSuggested; i++) {
- hr = videoService->CreateSurface(
- request->Info.Width, request->Info.Height, 0,
- format, D3DPOOL_DEFAULT, m_surfaceUsage, target,
- (IDirect3DSurface9 **)&dxMids[i].first,
- &dxMids[i].second);
- if (FAILED(hr)) {
- _dx9_simple_free(response);
- MSDK_SAFE_FREE(dxMids);
- MSDK_SAFE_FREE(dxMidPtrs);
- return MFX_ERR_MEMORY_ALLOC;
- }
- dxMidPtrs[i] = &dxMids[i];
- }
- } else {
- safe_array<IDirect3DSurface9 *> dxSrf(
- new IDirect3DSurface9 *[request->NumFrameSuggested]);
- if (!dxSrf.get()) {
- MSDK_SAFE_FREE(dxMids);
- MSDK_SAFE_FREE(dxMidPtrs);
- return MFX_ERR_MEMORY_ALLOC;
- }
- hr = videoService->CreateSurface(
- request->Info.Width, request->Info.Height,
- request->NumFrameSuggested - 1, format, D3DPOOL_DEFAULT,
- m_surfaceUsage, target, dxSrf.get(), NULL);
- if (FAILED(hr)) {
- MSDK_SAFE_FREE(dxMids);
- MSDK_SAFE_FREE(dxMidPtrs);
- return MFX_ERR_MEMORY_ALLOC;
- }
- for (int i = 0; i < request->NumFrameSuggested; i++) {
- dxMids[i].first = dxSrf.get()[i];
- dxMidPtrs[i] = &dxMids[i];
- }
- }
- return MFX_ERR_NONE;
- }
- mfxStatus dx9_simple_alloc(mfxHDL pthis, mfxFrameAllocRequest *request,
- mfxFrameAllocResponse *response)
- {
- mfxStatus sts = MFX_ERR_NONE;
- if (request->Type & MFX_MEMTYPE_SYSTEM_MEMORY)
- return MFX_ERR_UNSUPPORTED;
- if (dx9_allocDecodeResponses.find(pthis) !=
- dx9_allocDecodeResponses.end() &&
- MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
- MFX_MEMTYPE_FROM_DECODE & request->Type) {
- // Memory for this request was already allocated during manual allocation stage. Return saved response
- // When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed.
- // Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response
- // (No such restriction applies to Encode or VPP)
- *response = dx9_allocDecodeResponses[pthis];
- dx9_allocDecodeRefCount[pthis]++;
- } else {
- sts = _dx9_simple_alloc(request, response);
- if (MFX_ERR_NONE == sts) {
- if (MFX_MEMTYPE_EXTERNAL_FRAME & request->Type &&
- MFX_MEMTYPE_FROM_DECODE & request->Type) {
- // Decode alloc response handling
- dx9_allocDecodeResponses[pthis] = *response;
- dx9_allocDecodeRefCount[pthis]++;
- } else {
- // Encode and VPP alloc response handling
- dx9_allocResponses[response->mids] = pthis;
- }
- }
- }
- return sts;
- }
|