| @@ -37,6 +37,9 @@ | |||
| #include "pixdesc.h" | |||
| #include "pixfmt.h" | |||
| typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT); | |||
| typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **); | |||
| typedef struct DXVA2FramesContext { | |||
| IDirect3DSurface9 **surfaces_internal; | |||
| int nb_surfaces_used; | |||
| @@ -47,6 +50,16 @@ typedef struct DXVA2FramesContext { | |||
| D3DFORMAT format; | |||
| } DXVA2FramesContext; | |||
| typedef struct DXVA2DevicePriv { | |||
| HMODULE d3dlib; | |||
| HMODULE dxva2lib; | |||
| HANDLE device_handle; | |||
| IDirect3D9 *d3d9; | |||
| IDirect3DDevice9 *d3d9device; | |||
| } DXVA2DevicePriv; | |||
| static const struct { | |||
| D3DFORMAT d3d_format; | |||
| enum AVPixelFormat pix_fmt; | |||
| @@ -273,6 +286,125 @@ static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, | |||
| return 0; | |||
| } | |||
| static void dxva2_device_free(AVHWDeviceContext *ctx) | |||
| { | |||
| AVDXVA2DeviceContext *hwctx = ctx->hwctx; | |||
| DXVA2DevicePriv *priv = ctx->user_opaque; | |||
| if (hwctx->devmgr && priv->device_handle != INVALID_HANDLE_VALUE) | |||
| IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, priv->device_handle); | |||
| if (hwctx->devmgr) | |||
| IDirect3DDeviceManager9_Release(hwctx->devmgr); | |||
| if (priv->d3d9device) | |||
| IDirect3DDevice9_Release(priv->d3d9device); | |||
| if (priv->d3d9) | |||
| IDirect3D9_Release(priv->d3d9); | |||
| if (priv->d3dlib) | |||
| FreeLibrary(priv->d3dlib); | |||
| if (priv->dxva2lib) | |||
| FreeLibrary(priv->dxva2lib); | |||
| av_freep(&ctx->user_opaque); | |||
| } | |||
| static int dxva2_device_create(AVHWDeviceContext *ctx, const char *device, | |||
| AVDictionary *opts, int flags) | |||
| { | |||
| AVDXVA2DeviceContext *hwctx = ctx->hwctx; | |||
| DXVA2DevicePriv *priv; | |||
| pDirect3DCreate9 *createD3D = NULL; | |||
| pCreateDeviceManager9 *createDeviceManager = NULL; | |||
| D3DPRESENT_PARAMETERS d3dpp = {0}; | |||
| D3DDISPLAYMODE d3ddm; | |||
| unsigned resetToken = 0; | |||
| UINT adapter = D3DADAPTER_DEFAULT; | |||
| HRESULT hr; | |||
| if (device) | |||
| adapter = atoi(device); | |||
| priv = av_mallocz(sizeof(*priv)); | |||
| if (!priv) | |||
| return AVERROR(ENOMEM); | |||
| ctx->user_opaque = priv; | |||
| ctx->free = dxva2_device_free; | |||
| priv->device_handle = INVALID_HANDLE_VALUE; | |||
| priv->d3dlib = LoadLibrary("d3d9.dll"); | |||
| if (!priv->d3dlib) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to load D3D9 library\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| priv->dxva2lib = LoadLibrary("dxva2.dll"); | |||
| if (!priv->dxva2lib) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to load DXVA2 library\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| createD3D = (pDirect3DCreate9 *)GetProcAddress(priv->d3dlib, "Direct3DCreate9"); | |||
| if (!createD3D) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(priv->dxva2lib, | |||
| "DXVA2CreateDirect3DDeviceManager9"); | |||
| if (!createDeviceManager) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| priv->d3d9 = createD3D(D3D_SDK_VERSION); | |||
| if (!priv->d3d9) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm); | |||
| d3dpp.Windowed = TRUE; | |||
| d3dpp.BackBufferWidth = 640; | |||
| d3dpp.BackBufferHeight = 480; | |||
| d3dpp.BackBufferCount = 0; | |||
| d3dpp.BackBufferFormat = d3ddm.Format; | |||
| d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; | |||
| d3dpp.Flags = D3DPRESENTFLAG_VIDEO; | |||
| hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), | |||
| D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, | |||
| &d3dpp, &priv->d3d9device); | |||
| if (FAILED(hr)) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| hr = createDeviceManager(&resetToken, &hwctx->devmgr); | |||
| if (FAILED(hr)) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device manager\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| hr = IDirect3DDeviceManager9_ResetDevice(hwctx->devmgr, priv->d3d9device, resetToken); | |||
| if (FAILED(hr)) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to bind Direct3D device to device manager\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &priv->device_handle); | |||
| if (FAILED(hr)) { | |||
| av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n"); | |||
| return AVERROR_UNKNOWN; | |||
| } | |||
| return 0; | |||
| } | |||
| const HWContextType ff_hwcontext_type_dxva2 = { | |||
| .type = AV_HWDEVICE_TYPE_DXVA2, | |||
| .name = "DXVA2", | |||
| @@ -281,6 +413,7 @@ const HWContextType ff_hwcontext_type_dxva2 = { | |||
| .frames_hwctx_size = sizeof(AVDXVA2FramesContext), | |||
| .frames_priv_size = sizeof(DXVA2FramesContext), | |||
| .device_create = dxva2_device_create, | |||
| .frames_init = dxva2_frames_init, | |||
| .frames_uninit = dxva2_frames_uninit, | |||
| .frames_get_buffer = dxva2_get_buffer, | |||