Exemple #1
0
static int dxva2_device_create9(AVHWDeviceContext *ctx, UINT adapter)
{
    DXVA2DevicePriv *priv = ctx->user_opaque;
    D3DPRESENT_PARAMETERS d3dpp = dxva2_present_params;
    D3DDISPLAYMODE d3ddm;
    HRESULT hr;
    pDirect3DCreate9 *createD3D = (pDirect3DCreate9 *)GetProcAddress(priv->d3dlib, "Direct3DCreate9");
    if (!createD3D) {
        av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\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.BackBufferFormat = d3ddm.Format;

    hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(),
                                FF_D3DCREATE_FLAGS,
                                &d3dpp, &priv->d3d9device);
    if (FAILED(hr)) {
        av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n");
        return AVERROR_UNKNOWN;
    }

    return 0;
}
Exemple #2
0
static int create_device(struct lavc_ctx *s)
{
    DXVA2Context *ctx = s->hwdec_priv;
    pDirect3DCreate9      *createD3D = NULL;
    HRESULT hr;
    D3DPRESENT_PARAMETERS d3dpp = {0};
    D3DDISPLAYMODE        d3ddm;
    UINT adapter = D3DADAPTER_DEFAULT;

    if (s->hwdec_info && s->hwdec_info->hwctx && s->hwdec_info->hwctx->d3d_ctx) {
        ctx->d3d9device = s->hwdec_info->hwctx->d3d_ctx->d3d9_device;
        if (ctx->d3d9device) {
            IDirect3D9_AddRef(ctx->d3d9device);
            MP_VERBOSE(ctx, "Using VO-supplied device %p.\n", ctx->d3d9device);
            return 0;
        }
    }

    ctx->d3dlib = LoadLibrary(L"d3d9.dll");
    if (!ctx->d3dlib) {
        MP_ERR(ctx, "Failed to load D3D9 library\n");
        goto fail;
    }

    createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9");
    if (!createD3D) {
        MP_ERR(ctx, "Failed to locate Direct3DCreate9\n");
        goto fail;
    }

    ctx->d3d9 = createD3D(D3D_SDK_VERSION);
    if (!ctx->d3d9) {
        MP_ERR(ctx, "Failed to create IDirect3D object\n");
        goto fail;
    }

    IDirect3D9_GetAdapterDisplayMode(ctx->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(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(),
                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
                                 &d3dpp, &ctx->d3d9device);
    if (FAILED(hr)) {
        MP_ERR(ctx, "Failed to create Direct3D device\n");
        goto fail;
    }

    return 0;

fail:
    return -1;
}
// This must be run before the konvergo main window switches to FS mode.
void initD3DDevice(void)
{
  // Boilerplate for creating a "blank" D3D device.
  // Most of this is copied from FFmpeg (LGPL).
  pDirect3DCreate9 *createD3D = NULL;
  HRESULT hr;
  D3DPRESENT_PARAMETERS d3dpp = {};
  D3DDISPLAYMODE        d3ddm;
  UINT adapter = D3DADAPTER_DEFAULT;

  HMODULE d3dlib = LoadLibraryW(L"d3d9.dll");
  if (!d3dlib) {
      QLOG_ERROR() << "Failed to load D3D9 library";
      return;
  }

  createD3D = (pDirect3DCreate9 *)GetProcAddress(d3dlib, "Direct3DCreate9");
  if (!createD3D) {
      QLOG_ERROR() << "Failed to locate Direct3DCreate9";
      return;
  }

  IDirect3D9 *d3d9 = createD3D(D3D_SDK_VERSION);
  if (!d3d9) {
      QLOG_ERROR() << "Failed to create IDirect3D object";
      return;
  }

  IDirect3D9_GetAdapterDisplayMode(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(d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(),
                                D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
                                &d3dpp, &d3ddevice);
  if (FAILED(hr)) {
    QLOG_ERROR() << "Failed to create Direct3D device";
    return;
  }

  QLOG_INFO() << "Successfully created a Direct3D device";
};
Exemple #4
0
void fullscreen_get_current_display_dx9(int *bitdepth, int *width, int *height, int *refreshrate)
{
    D3DDISPLAYMODE mode;

    if (S_OK == IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT , &mode)) {
        *bitdepth = 32;
        *width = mode.Width;
        *height = mode.Height;
        *refreshrate = mode.RefreshRate;
    } else {
        /* provide defaults if GetDisplayMode fails for some reason */
        log_debug("fullscreen_get_current_display_dx9 failed to get mode!");
        *bitdepth = 32;
        *width = 640;
        *height = 480;
        *refreshrate = 0;
    }
}
Exemple #5
0
/**
 * It setup vout_display_sys_t::d3dpp and vout_display_sys_t::rect_display
 * from the default adapter.
 */
int D3D9_FillPresentationParameters(d3d9_handle_t *hd3d,
                                    const video_format_t *source, d3d9_device_t *out)
{
    /*
    ** Get the current desktop display mode, so we can set up a back
    ** buffer of the same format
    */
    D3DDISPLAYMODE d3ddm;
    if (source->i_width)
    {
        HRESULT hr = IDirect3D9_GetAdapterDisplayMode(hd3d->obj, out->adapterId, &d3ddm);
        if (FAILED(hr))
           return VLC_EGENERIC;
    }

    /* Set up the structure used to create the D3DDevice. */
    D3DPRESENT_PARAMETERS *d3dpp = &out->pp;
    ZeroMemory(d3dpp, sizeof(D3DPRESENT_PARAMETERS));
    d3dpp->Flags                  = D3DPRESENTFLAG_VIDEO;
    d3dpp->Windowed               = TRUE;
    d3dpp->MultiSampleType        = D3DMULTISAMPLE_NONE;
    d3dpp->PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
    d3dpp->EnableAutoDepthStencil = FALSE;
    if (source->i_width)
    {
        d3dpp->hDeviceWindow     = out->hwnd;
        d3dpp->SwapEffect        = D3DSWAPEFFECT_COPY;
        d3dpp->BackBufferFormat  = d3ddm.Format;
        d3dpp->BackBufferCount   = 1;
        d3dpp->BackBufferWidth   = __MAX((unsigned int)GetSystemMetrics(SM_CXVIRTUALSCREEN),
                                              source->i_width);
        d3dpp->BackBufferHeight  = __MAX((unsigned int)GetSystemMetrics(SM_CYVIRTUALSCREEN),
                                              source->i_height);
    }
    else
    {
        d3dpp->hDeviceWindow     = NULL;
        d3dpp->SwapEffect        = D3DSWAPEFFECT_DISCARD;
        d3dpp->BackBufferCount   = 0;
        d3dpp->BackBufferFormat  = D3DFMT_X8R8G8B8;    /* FIXME what to put here */
    }

    return VLC_SUCCESS;
}
Exemple #6
0
/**
 * It setup vout_display_sys_t::d3dpp and vout_display_sys_t::rect_display
 * from the default adapter.
 */
static int Direct3DFillPresentationParameters(vout_display_t *vd)
{
    vout_display_sys_t *sys = vd->sys;

    /*
    ** Get the current desktop display mode, so we can set up a back
    ** buffer of the same format
    */
    D3DDISPLAYMODE d3ddm;
    HRESULT hr = IDirect3D9_GetAdapterDisplayMode(sys->d3dobj,
                                                  D3DADAPTER_DEFAULT, &d3ddm);
    if (FAILED(hr)) {
       msg_Err(vd, "Could not read adapter display mode. (hr=0x%lX)", hr);
       return VLC_EGENERIC;
    }

    /* Set up the structure used to create the D3DDevice. */
    D3DPRESENT_PARAMETERS *d3dpp = &vd->sys->d3dpp;
    ZeroMemory(d3dpp, sizeof(D3DPRESENT_PARAMETERS));
    d3dpp->Flags                  = D3DPRESENTFLAG_VIDEO;
    d3dpp->Windowed               = TRUE;
    d3dpp->hDeviceWindow          = vd->sys->hvideownd;
    d3dpp->BackBufferWidth        = __MAX((unsigned int)GetSystemMetrics(SM_CXVIRTUALSCREEN),
                                          d3ddm.Width);
    d3dpp->BackBufferHeight       = __MAX((unsigned int)GetSystemMetrics(SM_CYVIRTUALSCREEN),
                                          d3ddm.Height);
    d3dpp->SwapEffect             = D3DSWAPEFFECT_COPY;
    d3dpp->MultiSampleType        = D3DMULTISAMPLE_NONE;
    d3dpp->PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT;
    d3dpp->BackBufferFormat       = d3ddm.Format;
    d3dpp->BackBufferCount        = 1;
    d3dpp->EnableAutoDepthStencil = FALSE;

    /* */
    RECT *display = &vd->sys->rect_display;
    display->left   = 0;
    display->top    = 0;
    display->right  = d3dpp->BackBufferWidth;
    display->bottom = d3dpp->BackBufferHeight;

    return VLC_SUCCESS;
}
Exemple #7
0
/** @brief Configure initial Direct3D context. The first
 *  function called to initialize the D3D context.
 *  @return 1 on success, 0 on failure
 */
static int configure_d3d(void)
{
    D3DDISPLAYMODE disp_mode;
    D3DVIEWPORT9 vp = {0, 0, vo_dwidth, vo_dheight, 0, 1};

    mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>configure_d3d called.\n");

    destroy_d3d_surfaces();

    /* Get the current desktop display mode, so we can set up a back buffer
     * of the same format. */
    if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle,
                                                D3DADAPTER_DEFAULT,
                                                &disp_mode))) {
        mp_msg(MSGT_VO, MSGL_ERR,
               "<vo_direct3d>Reading adapter display mode failed.\n");
        return 0;
    }

    /* Write current Desktop's colorspace format in the global storage. */
    priv->desktop_fmt = disp_mode.Format;

    if (!change_d3d_backbuffer(BACKBUFFER_CREATE))
        return 0;

    if (!create_d3d_surfaces())
        return 0;

    if (FAILED(IDirect3DDevice9_SetViewport(priv->d3d_device,
                                            &vp))) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Setting viewport failed.\n");
        return 0;
    }

    calc_fs_rect();

    return 1;
}
Exemple #8
0
static int preinit(const char *arg)
{
    D3DDISPLAYMODE disp_mode;
    D3DCAPS9 disp_caps;
    DWORD texture_caps;
    DWORD dev_caps;

    /* Set to zero all global variables. */
    priv = calloc(1, sizeof(struct global_priv));
    if (!priv) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Allocating private memory failed.\n");
        goto err_out;
    }

    /* FIXME
       > Please use subopt-helper.h for this, see vo_gl.c:preinit for
       > an example of how to use it.
    */

    priv->d3d9_dll = LoadLibraryA("d3d9.dll");
    if (!priv->d3d9_dll) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Unable to dynamically load d3d9.dll\n");
        goto err_out;
    }

    priv->pDirect3DCreate9 = (void *)GetProcAddress(priv->d3d9_dll, "Direct3DCreate9");
    if (!priv->pDirect3DCreate9) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Unable to find entry point of Direct3DCreate9\n");
        goto err_out;
    }

    priv->d3d_handle = priv->pDirect3DCreate9(D3D_SDK_VERSION);
    if (!priv->d3d_handle) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Initializing Direct3D failed.\n");
        goto err_out;
    }

    if (FAILED(IDirect3D9_GetAdapterDisplayMode(priv->d3d_handle,
                                                D3DADAPTER_DEFAULT,
                                                &disp_mode))) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Reading display mode failed.\n");
        goto err_out;
    }

    /* Store in priv->desktop_fmt the user desktop's colorspace. Usually XRGB. */
    priv->desktop_fmt = disp_mode.Format;
    priv->cur_backbuf_width = disp_mode.Width;
    priv->cur_backbuf_height = disp_mode.Height;

    mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Setting backbuffer dimensions to (%dx%d).\n",
           disp_mode.Width, disp_mode.Height);

    if (FAILED(IDirect3D9_GetDeviceCaps(priv->d3d_handle,
                                        D3DADAPTER_DEFAULT,
                                        D3DDEVTYPE_HAL,
                                        &disp_caps))) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Reading display capabilities failed.\n");
        goto err_out;
    }

    /* Store relevant information reguarding caps of device */
    texture_caps                  = disp_caps.TextureCaps;
    dev_caps                      = disp_caps.DevCaps;
    priv->device_caps_power2_only =  (texture_caps & D3DPTEXTURECAPS_POW2) &&
                                    !(texture_caps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
    priv->device_caps_square_only = texture_caps & D3DPTEXTURECAPS_SQUAREONLY;
    priv->device_texture_sys      = dev_caps & D3DDEVCAPS_TEXTURESYSTEMMEMORY;
    priv->max_texture_width       = disp_caps.MaxTextureWidth;
    priv->max_texture_height      = disp_caps.MaxTextureHeight;

    mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>device_caps_power2_only %d, device_caps_square_only %d\n"
                            "<vo_direct3d>device_texture_sys %d\n"
                            "<vo_direct3d>max_texture_width %d, max_texture_height %d\n",
           priv->device_caps_power2_only, priv->device_caps_square_only,
           priv->device_texture_sys, priv->max_texture_width,
           priv->max_texture_height);

    /* w32_common framework call. Configures window on the screen, gets
     * fullscreen dimensions and does other useful stuff.
     */
    if (!vo_w32_init()) {
        mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Configuring onscreen window failed.\n");
        goto err_out;
    }

    return 0;

err_out:
    uninit();
    return -1;
}
/**
    \fn changeZoom
*/
bool dxvaRender::init( GUI_WindowInfo *  window, uint32_t w, uint32_t h,renderZoom zoom)
{
    ADM_info("Initializing dxva2/D3D render\n");
    info=*window;
    baseInit(w,h,zoom);

    windowId=(HWND)window->systemWindowId;

    if(!d3dHandle)
    {
        ADM_warning("No D3DHandle\n");
        return false;
    }

    if (ADM_FAILED(IDirect3D9_GetAdapterDisplayMode(d3dHandle,
                                                D3DADAPTER_DEFAULT,
                                                &displayMode)))
    {
        ADM_warning("Dxv2/D3D Render: Cannot get display mode\n");
        return 0;
    }

    D3DCAPS9 deviceCapabilities;
    ADM_info("D3D Checking device capabilities\n");
    if (ADM_FAILED(IDirect3D9_GetDeviceCaps(d3dHandle,
                                        D3DADAPTER_DEFAULT,
                                        D3DDEVTYPE_HAL,
                                        &deviceCapabilities)))
    {
      ADM_warning("Cannot get device capabilities");
      return false;
    }
    int texture = deviceCapabilities.TextureCaps;
    ADM_info("Power of 2 : %d\n",  (texture & D3DPTEXTURECAPS_POW2) &&   !(texture & D3DPTEXTURECAPS_NONPOW2CONDITIONAL));
    ADM_info("Square only: %d\n",  (texture & D3DPTEXTURECAPS_SQUAREONLY));



      // Check if we support YV12
    D3DFORMAT fmt=displayMode.Format;
    D3DFORMAT yv12=(D3DFORMAT)MAKEFOURCC('Y','V','1','2');
    if (ADM_FAILED(IDirect3D9_CheckDeviceFormatConversion(   d3dHandle, // adapter
                                                         D3DADAPTER_DEFAULT, // device type
                                                         D3DDEVTYPE_HAL, // adapter format
                                                         yv12, // render target format
                                                         fmt)))  // depth stencil format
    {
        useYV12=false;
        ADM_info("D3D YV12 not supported\n");
    }
    else
    {
        useYV12=true;
        ADM_info("D3D YV12 is supported\n");
    }



    if(!setup())
    {
      ADM_warning("Dxva/D3D setup failed\n");
      return false;
    }
    videoWidget=(ADM_Qvideo *)info.widget;
    videoWidget->useExternalRedraw(true); // deactivate Qt Double buffering
    videoWidget->setDrawer(this);

    ADM_info("Dxva (D3D) init successful, dxva render. w=%d, h=%d,zoom=%d, displayWidth=%d, displayHeight=%d\n",(int)w,(int)h,(int)zoom,(int)displayWidth,(int)displayHeight);
    return true;
}
Exemple #10
0
static HRESULT get_adapter_display_mode(base *d3dptr, UINT adapter, D3DDISPLAYMODE *mode)
{
	IDirect3D9 *d3d9 = (IDirect3D9 *)d3dptr->d3dobj;
	return IDirect3D9_GetAdapterDisplayMode(d3d9, adapter, mode);
}
Exemple #11
0
static int dxva2_alloc(AVCodecContext *s)
{
    HwAccelContext  *hac = s->opaque;
    DXVA2Context *ctx;
    pDirect3DCreate9      *createD3D = NULL;
    pCreateDeviceManager9 *createDeviceManager = NULL;
    HRESULT hr;
    D3DPRESENT_PARAMETERS d3dpp = {0};
    D3DDISPLAYMODE        d3ddm;
    unsigned resetToken = 0;
    UINT adapter = D3DADAPTER_DEFAULT;

    ctx = av_mallocz(sizeof(*ctx));
    if (!ctx)
        return AVERROR(ENOMEM);

    ctx->deviceHandle = INVALID_HANDLE_VALUE;

    hac->hwaccel_ctx           = ctx;
    hac->hwaccel_uninit        = dxva2_uninit;
    hac->hwaccel_get_buffer    = dxva2_get_buffer;
    hac->hwaccel_retrieve_data = dxva2_retrieve_data;

    ctx->d3dlib = LoadLibrary("d3d9.dll");
    if (!ctx->d3dlib) {
        av_log(NULL, loglevel, "Failed to load D3D9 library\n");
        goto fail;
    }
    ctx->dxva2lib = LoadLibrary("dxva2.dll");
    if (!ctx->dxva2lib) {
        av_log(NULL, loglevel, "Failed to load DXVA2 library\n");
        goto fail;
    }

    createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9");
    if (!createD3D) {
        av_log(NULL, loglevel, "Failed to locate Direct3DCreate9\n");
        goto fail;
    }
    createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(ctx->dxva2lib, "DXVA2CreateDirect3DDeviceManager9");
    if (!createDeviceManager) {
        av_log(NULL, loglevel, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
        goto fail;
    }

    ctx->d3d9 = createD3D(D3D_SDK_VERSION);
    if (!ctx->d3d9) {
        av_log(NULL, loglevel, "Failed to create IDirect3D object\n");
        goto fail;
    }

    if (hac->hwaccel_device) {
        adapter = atoi(hac->hwaccel_device);
        av_log(NULL, AV_LOG_INFO, "Using HWAccel device %d\n", adapter);
    }

    IDirect3D9_GetAdapterDisplayMode(ctx->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(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(),
                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
                                 &d3dpp, &ctx->d3d9device);
    if (FAILED(hr)) {
        av_log(NULL, loglevel, "Failed to create Direct3D device\n");
        goto fail;
    }

    hr = createDeviceManager(&resetToken, &ctx->d3d9devmgr);
    if (FAILED(hr)) {
        av_log(NULL, loglevel, "Failed to create Direct3D device manager\n");
        goto fail;
    }

    hr = IDirect3DDeviceManager9_ResetDevice(ctx->d3d9devmgr, ctx->d3d9device, resetToken);
    if (FAILED(hr)) {
        av_log(NULL, loglevel, "Failed to bind Direct3D device to device manager\n");
        goto fail;
    }

    hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle);
    if (FAILED(hr)) {
        av_log(NULL, loglevel, "Failed to open device handle\n");
        goto fail;
    }

    hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service);
    if (FAILED(hr)) {
        av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n");
        goto fail;
    }

    ctx->tmp_frame = av_frame_alloc();
    if (!ctx->tmp_frame)
        goto fail;

    s->hwaccel_context = av_mallocz(sizeof(struct dxva_context));
    if (!s->hwaccel_context)
        goto fail;

    return 0;
fail:
    dxva2_uninit(s);
    return AVERROR(EINVAL);
}
Exemple #12
0
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;
}
Exemple #13
0
static void test_get_adapter_displaymode_ex(void)
{
    HWND window = create_window();
    IDirect3D9 *d3d9 = (void *) 0xdeadbeef;
    IDirect3D9Ex *d3d9ex;
    UINT count;
    HRESULT hr;
    D3DDISPLAYMODE mode;
    D3DDISPLAYMODEEX mode_ex;
    D3DDISPLAYROTATION rotation;
    HANDLE hdll;
    DEVMODEA startmode;
    LONG retval;

    hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
    if (FAILED(hr))
    {
        skip("Direct3D9Ex is not available (%#x)\n", hr);
        DestroyWindow(window);
        return;
    }

    count = IDirect3D9Ex_GetAdapterCount(d3d9ex);
    if (!count)
    {
        skip("No adapters available.\n");
        IDirect3D9Ex_Release(d3d9ex);
        DestroyWindow(window);
        return;
    }

    hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9);
    ok(hr == D3D_OK,
       "IDirect3D9Ex::QueryInterface for IID_IDirect3D9 returned %08x, expected D3D_OK\n",
       hr);
    ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef,
       "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9);
    /* change displayorientation*/
    hdll = GetModuleHandleA("user32.dll");
    pEnumDisplaySettingsExA = (void*)GetProcAddress(hdll, "EnumDisplaySettingsExA");
    pChangeDisplaySettingsExA = (void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");

    if (!pEnumDisplaySettingsExA || !pChangeDisplaySettingsExA) goto out;

    memset(&startmode, 0, sizeof(startmode));
    startmode.dmSize = sizeof(startmode);
    retval = pEnumDisplaySettingsExA(NULL, ENUM_CURRENT_SETTINGS, &startmode, 0);
    ok(retval, "Failed to retrieve current display mode, retval %d.\n", retval);
    if (!retval) goto out;

    startmode.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT;
    S2(U1(startmode)).dmDisplayOrientation = DMDO_180;
    retval = pChangeDisplaySettingsExA(NULL, &startmode, NULL, 0, NULL);

    if(retval == DISP_CHANGE_BADMODE)
    {
        trace(" Test skipped: graphics mode is not supported\n");
        goto out;
    }

    ok(retval == DISP_CHANGE_SUCCESSFUL,"ChangeDisplaySettingsEx failed with %d\n", retval);
    /* try retrieve orientation info with EnumDisplaySettingsEx*/
    startmode.dmFields = 0;
    S2(U1(startmode)).dmDisplayOrientation = 0;
    ok(pEnumDisplaySettingsExA(NULL, ENUM_CURRENT_SETTINGS, &startmode, EDS_ROTATEDMODE), "EnumDisplaySettingsEx failed\n");

    /*now that orientation has changed start tests for GetAdapterDisplayModeEx: invalid Size*/
    memset(&mode_ex, 0, sizeof(mode_ex));
    hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, &rotation);
    todo_wine ok(hr == D3DERR_INVALIDCALL, "GetAdapterDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL\n", hr);

    mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
    /* invalid count*/
    hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, count + 1, &mode_ex, &rotation);
    todo_wine ok(hr == D3DERR_INVALIDCALL, "GetAdapterDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL\n", hr);
    /*valid count and valid Size*/
    hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, &rotation);
    todo_wine ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr);

    /* Compare what GetAdapterDisplayMode returns with what GetAdapterDisplayModeEx returns*/
    hr = IDirect3D9_GetAdapterDisplayMode(d3d9, D3DADAPTER_DEFAULT, &mode);
    ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);

    ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "size is %d\n", mode_ex.Size);
    todo_wine ok(mode_ex.Width == mode.Width, "width is %d instead of %d\n", mode_ex.Width, mode.Width);
    todo_wine ok(mode_ex.Height == mode.Height, "height is %d instead of %d\n", mode_ex.Height, mode.Height);
    todo_wine ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d\n", mode_ex.RefreshRate, mode.RefreshRate);
    todo_wine ok(mode_ex.Format == mode.Format, "format is %x instead of %x\n", mode_ex.Format, mode.Format);
    /* don't know yet how to test for ScanLineOrdering, just testing that it is set to a value by GetAdapterDisplayModeEx*/
    todo_wine ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");
    /* check that orientation is returned correctly by GetAdapterDisplayModeEx and EnumDisplaySettingsEx*/
    todo_wine ok(S2(U1(startmode)).dmDisplayOrientation == DMDO_180 && rotation == D3DDISPLAYROTATION_180, "rotation is %d instead of %d\n", rotation, S2(U1(startmode)).dmDisplayOrientation);

    trace("GetAdapterDisplayModeEx returned Width = %d,Height = %d, RefreshRate = %d, Format = %x, ScanLineOrdering = %x, rotation = %d\n",
          mode_ex.Width, mode_ex.Height, mode_ex.RefreshRate, mode_ex.Format, mode_ex.ScanLineOrdering, rotation);

    /* test GetAdapterDisplayModeEx with null pointer for D3DDISPLAYROTATION */
    memset(&mode_ex, 0, sizeof(mode_ex));
    mode_ex.Size = sizeof(D3DDISPLAYMODEEX);

    hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, NULL);
    todo_wine ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr);

    ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "size is %d\n", mode_ex.Size);
    todo_wine ok(mode_ex.Width == mode.Width, "width is %d instead of %d\n", mode_ex.Width, mode.Width);
    todo_wine ok(mode_ex.Height == mode.Height, "height is %d instead of %d\n", mode_ex.Height, mode.Height);
    todo_wine ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d\n", mode_ex.RefreshRate, mode.RefreshRate);
    todo_wine ok(mode_ex.Format == mode.Format, "format is %x instead of %x\n", mode_ex.Format, mode.Format);
    /* don't know yet how to test for ScanLineOrdering, just testing that it is set to a value by GetAdapterDisplayModeEx*/
    todo_wine ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");

    /* return to the default mode */
    pChangeDisplaySettingsExA(NULL, NULL, NULL, 0, NULL);
out:
    IDirect3D9_Release(d3d9);
    IDirect3D9Ex_Release(d3d9ex);
}
static GstCaps *
gst_dx9screencapsrc_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
{
  GstDX9ScreenCapSrc *src = GST_DX9SCREENCAPSRC (bsrc);
  RECT rect_dst;
  GstCaps *caps;

  if (src->monitor >= IDirect3D9_GetAdapterCount (g_d3d9)) {
    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
      ("Specified monitor with index %d not found", src->monitor), (NULL));
    return NULL;
  }

  if (FAILED (IDirect3D9_GetAdapterDisplayMode (g_d3d9, src->monitor,
              &src->disp_mode))) {
    return NULL;
  }

  SetRect (&rect_dst, 0, 0, src->disp_mode.Width, src->disp_mode.Height);
  src->screen_rect = rect_dst;

  if (src->capture_w && src->capture_h &&
      src->capture_x + src->capture_w < rect_dst.right - rect_dst.left &&
      src->capture_y + src->capture_h < rect_dst.bottom - rect_dst.top) {
    rect_dst.left = src->capture_x;
    rect_dst.top = src->capture_y;
    rect_dst.right = src->capture_x + src->capture_w;
    rect_dst.bottom = src->capture_y + src->capture_h;
  } else {
    /* Default values */
    src->capture_x = src->capture_y = 0;
    src->capture_w = src->capture_h = 0;
  }

  /* Note:
   *    Expose as xRGB even though the Surface is allocated as ARGB!
   *    This is due to IDirect3DDevice9_GetFrontBufferData which only takes
   *    ARGB surface, but the A channel is in reality never used.
   *    I should add that I had problems specifying ARGB. It might be a bug
   *    in ffmpegcolorspace which I used for testing.
   *    Another interesting thing is that directdrawsink did not support ARGB,
   *    but only xRGB. (On my system, using 32b color depth) And according to
   *    the DirectX documentation ARGB is NOT a valid display buffer format,
   *    but xRGB is.
   */
  caps = gst_caps_new_simple ("video/x-raw",
      "format", G_TYPE_STRING, "BGRx",
      "width", G_TYPE_INT, rect_dst.right - rect_dst.left,
      "height", G_TYPE_INT, rect_dst.bottom - rect_dst.top,
      "framerate", GST_TYPE_FRACTION_RANGE, 1, 1, G_MAXINT, 1,
      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);

  if (filter) {
    GstCaps *tmp =
        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
    gst_caps_unref (caps);
    caps = tmp;
  }

  return caps;
}
Exemple #15
0
Fichier : dxva2.c Projet : 2ion/mpv
static int dxva2_init_decoder(struct lavc_ctx *s, int w, int h)
{
    HRESULT hr;
    int ret = -1;
    struct priv *p = s->hwdec_priv;
    TA_FREEP(&p->decoder_pool);

    int  n_surfaces = hwdec_get_max_refs(s) + ADDITIONAL_SURFACES;
    IDirect3DSurface9    **surfaces = NULL;
    IDirectXVideoDecoder  *decoder  = NULL;
    void                  *tmp      = talloc_new(NULL);

    UINT n_guids;
    GUID *device_guids;
    hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(
        p->decoder_service, &n_guids, &device_guids);
    if (FAILED(hr)) {
        MP_ERR(p, "Failed to retrieve decoder device GUIDs: %s\n",
               mp_HRESULT_to_str(hr));
        goto done;
    }

    dump_decoder_info(s, device_guids, n_guids);

    struct d3d_decoder_fmt fmt =
        d3d_select_decoder_mode(s, device_guids, n_guids, get_dxfmt_cb);
    CoTaskMemFree(device_guids);
    if (fmt.mpfmt_decoded == IMGFMT_NONE) {
        MP_ERR(p, "Failed to find a suitable decoder\n");
        goto done;
    }

    p->mpfmt_decoded = fmt.mpfmt_decoded;
    struct mp_image_pool *decoder_pool =
        talloc_steal(tmp, mp_image_pool_new(n_surfaces));
    DXVA2_ConfigPictureDecode *decoder_config =
        talloc_zero(decoder_pool, DXVA2_ConfigPictureDecode);

    int w_align = w, h_align = h;
    d3d_surface_align(s, &w_align, &h_align);
    DXVA2_VideoDesc video_desc ={
        .SampleWidth  = w,
        .SampleHeight = h,
        .Format       = fmt.dxfmt_decoded,
    };
    UINT                     n_configs  = 0;
    DXVA2_ConfigPictureDecode *configs = NULL;
    hr = IDirectXVideoDecoderService_GetDecoderConfigurations(
        p->decoder_service, fmt.guid, &video_desc, NULL,
        &n_configs, &configs);
    if (FAILED(hr)) {
        MP_ERR(p, "Unable to retrieve decoder configurations: %s\n",
               mp_HRESULT_to_str(hr));
        goto done;
    }

    unsigned max_score = 0;
    for (UINT i = 0; i < n_configs; i++) {
        unsigned score = d3d_decoder_config_score(
            s, &configs[i].guidConfigBitstreamEncryption,
            configs[i].ConfigBitstreamRaw);
        if (score > max_score) {
            max_score       = score;
            *decoder_config = configs[i];
        }
    }
    CoTaskMemFree(configs);
    if (!max_score) {
        MP_ERR(p, "Failed to find a suitable decoder configuration\n");
        goto done;
    }

    surfaces = talloc_zero_array(decoder_pool, IDirect3DSurface9*, n_surfaces);
    hr = IDirectXVideoDecoderService_CreateSurface(
        p->decoder_service,
        w_align, h_align,
        n_surfaces - 1, fmt.dxfmt_decoded, D3DPOOL_DEFAULT, 0,
        DXVA2_VideoDecoderRenderTarget, surfaces, NULL);
    if (FAILED(hr)) {
        MP_ERR(p, "Failed to create %d video surfaces: %s\n",
               n_surfaces, mp_HRESULT_to_str(hr));
        goto done;
    }

    hr = IDirectXVideoDecoderService_CreateVideoDecoder(
        p->decoder_service, fmt.guid, &video_desc, decoder_config,
        surfaces, n_surfaces, &decoder);
    if (FAILED(hr)) {
        MP_ERR(p, "Failed to create DXVA2 video decoder: %s\n",
               mp_HRESULT_to_str(hr));
        goto done;
    }

    for (int i = 0; i < n_surfaces; i++) {
        struct mp_image *img = dxva2_new_ref(decoder, surfaces[i], w, h);
        if (!img) {
            MP_ERR(p, "Failed to create DXVA2 image\n");
            goto done;
        }
        mp_image_pool_add(decoder_pool, img); // transferred to pool
    }

    // Pass required information on to ffmpeg.
    struct dxva_context *dxva_ctx = s->avctx->hwaccel_context;
    dxva_ctx->cfg           = decoder_config;
    dxva_ctx->decoder       = decoder;
    dxva_ctx->surface_count = n_surfaces;
    dxva_ctx->surface       = surfaces;
    dxva_ctx->workaround    = is_clearvideo(fmt.guid) ?
                              FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO : 0;

    p->decoder_pool = talloc_steal(NULL, decoder_pool);
    ret = 0;
done:
    // On success, `p->decoder_pool` mp_images still hold refs to `surfaces` and
    // `decoder`, so the pointers in the ffmpeg `dxva_context` strcture remain
    // valid for the lifetime of the pool.
    if (surfaces) {
        for (int i = 0; i < n_surfaces; i++)
            IDirect3DSurface9_Release(surfaces[i]);
    }
    if (decoder)
        IDirectXVideoDecoder_Release(decoder);

    talloc_free(tmp);
    return ret;
}

static void destroy_device(struct lavc_ctx *s)
{
    struct priv *p = s->hwdec_priv;

    if (p->device)
        IDirect3DDevice9_Release(p->device);

    if (p->d3d9)
        IDirect3D9_Release(p->d3d9);

    if (p->d3d9_dll)
        FreeLibrary(p->d3d9_dll);

    if (p->dxva2_dll)
        FreeLibrary(p->dxva2_dll);
}

static bool create_device(struct lavc_ctx *s)
{
    struct priv *p = s->hwdec_priv;
    p->d3d9_dll = LoadLibrary(L"d3d9.dll");
    if (!p->d3d9_dll) {
        MP_ERR(p, "Failed to load D3D9 library\n");
        return false;
    }

    IDirect3D9* (WINAPI *Direct3DCreate9)(UINT) =
        (void *)GetProcAddress(p->d3d9_dll, "Direct3DCreate9");
    if (!Direct3DCreate9) {
        MP_ERR(p, "Failed to locate Direct3DCreate9\n");
        return false;
    }

    p->d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
    if (!p->d3d9) {
        MP_ERR(p, "Failed to create IDirect3D object\n");
        return false;
    }

    UINT adapter = D3DADAPTER_DEFAULT;
    D3DDISPLAYMODE display_mode;
    IDirect3D9_GetAdapterDisplayMode(p->d3d9, adapter, &display_mode);
    D3DPRESENT_PARAMETERS present_params = {
        .Windowed         = TRUE,
        .BackBufferWidth  = 640,
        .BackBufferHeight = 480,
        .BackBufferCount  = 0,
        .BackBufferFormat = display_mode.Format,
        .SwapEffect       = D3DSWAPEFFECT_DISCARD,
        .Flags            = D3DPRESENTFLAG_VIDEO,
    };
    HRESULT hr = IDirect3D9_CreateDevice(p->d3d9, adapter,
                                         D3DDEVTYPE_HAL,
                                         GetShellWindow(),
                                         D3DCREATE_SOFTWARE_VERTEXPROCESSING |
                                         D3DCREATE_MULTITHREADED |
                                         D3DCREATE_FPU_PRESERVE,
                                         &present_params,
                                         &p->device);
    if (FAILED(hr)) {
        MP_ERR(p, "Failed to create Direct3D device: %s\n",
               mp_HRESULT_to_str(hr));
        return false;
    }
    return true;
}

static void dxva2_uninit(struct lavc_ctx *s)
{
    struct priv *p = s->hwdec_priv;
    if (!p)
        return;

    av_freep(&s->avctx->hwaccel_context);
    talloc_free(p->decoder_pool);

    if (p->decoder_service)
        IDirectXVideoDecoderService_Release(p->decoder_service);

    if (p->device_manager && p->device_handle != INVALID_HANDLE_VALUE)
        IDirect3DDeviceManager9_CloseDeviceHandle(p->device_manager, p->device_handle);

    if (p->device_manager)
        IDirect3DDeviceManager9_Release(p->device_manager);

    destroy_device(s);

    TA_FREEP(&s->hwdec_priv);
}

static int dxva2_init(struct lavc_ctx *s)
{
    HRESULT hr;
    struct priv *p = talloc_zero(NULL, struct priv);
    if (!p)
        return -1;

    s->hwdec_priv = p;
    p->device_handle = INVALID_HANDLE_VALUE;
    p->log           = mp_log_new(s, s->log, "dxva2");

    if (s->hwdec->type == HWDEC_DXVA2_COPY) {
        mp_check_gpu_memcpy(p->log, NULL);
        p->sw_pool = talloc_steal(p, mp_image_pool_new(17));
    }

    if (s->hwdec_info && s->hwdec_info->hwctx && s->hwdec_info->hwctx->d3d_ctx)
        p->device = s->hwdec_info->hwctx->d3d_ctx->d3d9_device;

    if (p->device) {
        IDirect3D9_AddRef(p->device);
        MP_VERBOSE(p, "Using VO-supplied device %p.\n", p->device);
    } else if (s->hwdec->type == HWDEC_DXVA2) {
        MP_ERR(p, "No Direct3D device provided for native dxva2 decoding\n");
        goto fail;
    } else {
        if (!create_device(s))
            goto fail;
    }

    p->dxva2_dll = LoadLibrary(L"dxva2.dll");
    if (!p->dxva2_dll) {
        MP_ERR(p, "Failed to load DXVA2 library\n");
        goto fail;
    }

    HRESULT (WINAPI *CreateDeviceManager9)(UINT *, IDirect3DDeviceManager9 **) =
        (void *)GetProcAddress(p->dxva2_dll,
                               "DXVA2CreateDirect3DDeviceManager9");
    if (!CreateDeviceManager9) {
        MP_ERR(p, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
        goto fail;
    }

    unsigned reset_token = 0;
    hr = CreateDeviceManager9(&reset_token, &p->device_manager);
    if (FAILED(hr)) {
        MP_ERR(p, "Failed to create Direct3D device manager: %s\n",
               mp_HRESULT_to_str(hr));
        goto fail;
    }

    hr = IDirect3DDeviceManager9_ResetDevice(p->device_manager,
                                             p->device, reset_token);
    if (FAILED(hr)) {
        MP_ERR(p, "Failed to bind Direct3D device to device manager: %s\n",
               mp_HRESULT_to_str(hr));
        goto fail;
    }

    hr = IDirect3DDeviceManager9_OpenDeviceHandle(p->device_manager,
                                                  &p->device_handle);
    if (FAILED(hr)) {
        MP_ERR(p, "Failed to open device handle: %s\n",
               mp_HRESULT_to_str(hr));
        goto fail;
    }

    hr = IDirect3DDeviceManager9_GetVideoService(
        p->device_manager, p->device_handle, &IID_IDirectXVideoDecoderService,
        (void **)&p->decoder_service);
    if (FAILED(hr)) {
        MP_ERR(p, "Failed to create IDirectXVideoDecoderService: %s\n",
               mp_HRESULT_to_str(hr));
        goto fail;
    }

    s->avctx->hwaccel_context = av_mallocz(sizeof(struct dxva_context));
    if (!s->avctx->hwaccel_context)
        goto fail;

    return 0;
fail:
    dxva2_uninit(s);
    return -1;
}

static int dxva2_probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
                       const char *codec)
{
    hwdec_request_api(info, "dxva2");
    // dxva2-copy can do without external context; dxva2 requires it.
    if (hwdec->type != HWDEC_DXVA2_COPY) {
        if (!info || !info->hwctx || !info->hwctx->d3d_ctx ||
            info->hwctx->type == HWDEC_DXVA2_COPY ||
            !info->hwctx->d3d_ctx->d3d9_device)
            return HWDEC_ERR_NO_CTX;
    }
    return d3d_probe_codec(codec);
}
IDirect3DDevice9 *d3dwin_open( char *title, unsigned int width_, unsigned int height_, D3DFORMAT format, BOOL fullscreen_ ){
	DIRECT3DCREATE9 Direct3DCreate9;
	RECT rect;
	WNDCLASS wc;
	UINT32 style;

	D3DDISPLAYMODE displaymode;
	D3DPRESENT_PARAMETERS presentparameters;
	D3DCAPS9 caps;

	width = width_;
	height = height_;
	fullscreen = fullscreen_;
	inst = GetModuleHandle(NULL);

	library = (HMODULE) LoadLibrary("d3d9.dll");
	if(!library) return NULL;
	Direct3DCreate9 = (DIRECT3DCREATE9) GetProcAddress(library,"Direct3DCreate9");
	if(!Direct3DCreate9) return NULL;
	direct3d=Direct3DCreate9(D3D_SDK_VERSION);
	if(!direct3d) return NULL;

	if(!fullscreen)
		style = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU;
	else{
		style = WS_POPUP;
		ShowCursor(FALSE);
	}

	rect.left = 0;
	rect.top = 0;
	rect.right = width;
	rect.bottom = height;

	if(!fullscreen) AdjustWindowRect( &rect, style, FALSE );
	
	wc.style = CS_VREDRAW|CS_HREDRAW;
	wc.lpfnWndProc = window_proc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = 0;
	wc.hIcon = LoadIcon(inst,MAKEINTRESOURCE(IDI_ICON));
	wc.hCursor = LoadCursor(inst,IDC_ARROW);
	wc.hbrBackground = 0;
	wc.lpszMenuName = 0;
	wc.lpszClassName = "d3d9";
	RegisterClass(&wc);
	
	win = CreateWindowEx(0, "d3d9", title, (style)|WS_VISIBLE, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0, 0, inst, 0);
	if(!win) return NULL;

	memset(&presentparameters, 0, sizeof(D3DPRESENT_PARAMETERS));
	if(!fullscreen){
		if(FAILED(IDirect3D9_GetAdapterDisplayMode( direct3d, D3DADAPTER_DEFAULT, &displaymode ))){
			d3dwin_close();
			return NULL;
		}
	}

	if(!fullscreen) presentparameters.Windowed = TRUE;

	presentparameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
	presentparameters.BackBufferWidth = width;
	presentparameters.BackBufferHeight = height;

	if( fullscreen ) presentparameters.BackBufferFormat = format;
	else presentparameters.BackBufferFormat = displaymode.Format;


	presentparameters.AutoDepthStencilFormat = D3DFMT_D24S8;
	presentparameters.EnableAutoDepthStencil = TRUE;

	IDirect3D9_GetDeviceCaps(direct3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);

	if(FAILED(IDirect3D9_CreateDevice( direct3d,
		D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		win,
		(caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&presentparameters,
		&device))){

		d3dwin_close();
		return NULL;
	}

	IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
	IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);

	return device;
}