{ NULL, 0 }
};
-/* */
-typedef struct {
- LPDIRECT3DSURFACE9 d3d;
- bool is_occupied;
-} DXVAPluginSurface;
+struct DXVAPluginSurface;
+typedef struct DXVAPluginSurface DXVAPluginSurface;
#define VA_DXVA2_MAX_SURFACE_COUNT (64)
typedef struct DXVAPluginContext
{
- /* Direct3D */
- D3DPRESENT_PARAMETERS d3dpp;
- LPDIRECT3D9 d3dobj;
- LPDIRECT3DDEVICE9 d3ddev;
-
- /* Device manager */
- IDirect3DDeviceManager9 *devmng;
- HANDLE hd3ddev;
-
/* Video service */
- IDirectXVideoDecoderService *vs;
GUID guid_decdev;
D3DFORMAT render_fmt;
/* Option conversion */
D3DFORMAT output;
- /* */
+ /* Surfaces */
unsigned surface_count;
int surface_width;
int surface_height;
+ DXVAPluginSurface *surface;
+ LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
int thread_count;
- DXVAPluginSurface surface[VA_DXVA2_MAX_SURFACE_COUNT];
- LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
-
struct dxva_context *hw_context;
} DXVAPluginContext;
-// FIXME : modify dxva_ctx to multi instance for multi-thread decoding.
-static DXVAPluginContext *dxva_ctx = &(DXVAPluginContext) {};
+struct DXVAPluginSurface {
+ LPDIRECT3DSURFACE9 d3d;
+ bool is_occupied;
+ DXVAPluginContext *dxva_ctx;
+};
-/* DLL */
-static HINSTANCE hd3d9_dll;
-static HINSTANCE hdxva2_dll;
+typedef struct DXVADeviceHandle
+{
+ /* DLL */
+ HINSTANCE hd3d9_dll;
+ HINSTANCE hdxva2_dll;
+ /* Direct3D */
+ LPDIRECT3D9 d3dobj;
+ LPDIRECT3DDEVICE9 d3ddev;
+
+ /* Device manager */
+ IDirect3DDeviceManager9 *devmng;
+ HANDLE hd3ddev;
+
+ /* Video service */
+ IDirectXVideoDecoderService *vs;
+} DXVADeviceHandle;
+static DXVADeviceHandle *dxva_dev = &(DXVADeviceHandle) {};
static const dxva2_mode_t *Dxva2FindMode(const GUID *guid)
{
{
/* */
LPDIRECT3D9 (WINAPI *Create9)(UINT SDKVersion);
- Create9 = (void *)GetProcAddress(hd3d9_dll, "Direct3DCreate9");
+ Create9 = (void *)GetProcAddress(dxva_dev->hd3d9_dll, "Direct3DCreate9");
if (!Create9) {
ERR("Cannot locate reference to Direct3DCreate9 ABI in DLL\n");
return -1;
ERR("Direct3DCreate9 failed\n");
return -1;
}
- dxva_ctx->d3dobj = d3dobj;
+ dxva_dev->d3dobj = d3dobj;
/* */
- D3DPRESENT_PARAMETERS *d3dpp = &dxva_ctx->d3dpp;
- ZeroMemory(d3dpp, sizeof(*d3dpp));
- d3dpp->Flags = D3DPRESENTFLAG_VIDEO;
- d3dpp->Windowed = TRUE;
- d3dpp->hDeviceWindow = NULL;
- d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE;
- d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
- d3dpp->BackBufferCount = 0; /* FIXME what to put here */
- d3dpp->BackBufferFormat = D3DFMT_X8R8G8B8; /* FIXME what to put here */
- d3dpp->BackBufferWidth = 0;
- d3dpp->BackBufferHeight = 0;
- d3dpp->EnableAutoDepthStencil = FALSE;
+ D3DPRESENT_PARAMETERS d3dpp;
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+ d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
+ d3dpp.Windowed = TRUE;
+ d3dpp.hDeviceWindow = NULL;
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ d3dpp.BackBufferCount = 0; /* FIXME what to put here */
+ d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; /* FIXME what to put here */
+ d3dpp.BackBufferWidth = 0;
+ d3dpp.BackBufferHeight = 0;
+ d3dpp.EnableAutoDepthStencil = FALSE;
/* Direct3D needs a HWND to create a device, even without using ::Present
this HWND is used to alert Direct3D when there's a change of focus window.
D3DDEVTYPE_HAL, GetDesktopWindow(),
D3DCREATE_SOFTWARE_VERTEXPROCESSING |
D3DCREATE_MULTITHREADED,
- d3dpp, &d3ddev))) {
+ &d3dpp, &d3ddev))) {
ERR("IDirect3D9_CreateDevice failed\n");
return -1;
}
- dxva_ctx->d3ddev = d3ddev;
+ dxva_dev->d3ddev = d3ddev;
return 0;
}
HRESULT (WINAPI *CreateDeviceManager9)(UINT *pResetToken,
IDirect3DDeviceManager9 **);
CreateDeviceManager9 =
- (void *)GetProcAddress(hdxva2_dll,
+ (void *)GetProcAddress(dxva_dev->hdxva2_dll,
"DXVA2CreateDirect3DDeviceManager9");
if (!CreateDeviceManager9) {
}
TRACE("OurDirect3DCreateDeviceManager9 Success!\n");
- dxva_ctx->devmng = devmng;
+ dxva_dev->devmng = devmng;
TRACE("obtained IDirect3DDeviceManager9\n");
- HRESULT hr = IDirect3DDeviceManager9_ResetDevice(devmng, dxva_ctx->d3ddev, token);
+ HRESULT hr = IDirect3DDeviceManager9_ResetDevice(devmng, dxva_dev->d3ddev, token);
if (FAILED(hr)) {
ERR("IDirect3DDeviceManager9_ResetDevice failed: %08x\n", (unsigned)hr);
return -1;
REFIID riid,
void **ppService);
CreateVideoService =
- (void *)GetProcAddress(hdxva2_dll, "DXVA2CreateVideoService");
+ (void *)GetProcAddress(dxva_dev->hdxva2_dll, "DXVA2CreateVideoService");
if (!CreateVideoService) {
ERR("cannot load function\n");
HRESULT hr;
HANDLE hd3ddev;
- hr = IDirect3DDeviceManager9_OpenDeviceHandle(dxva_ctx->devmng, &hd3ddev);
+ hr = IDirect3DDeviceManager9_OpenDeviceHandle(dxva_dev->devmng, &hd3ddev);
if (FAILED(hr)) {
ERR("OpenDeviceHandle failed\n");
return -1;
}
- dxva_ctx->hd3ddev = hd3ddev;
+ dxva_dev->hd3ddev = hd3ddev;
void *pv;
- hr = IDirect3DDeviceManager9_GetVideoService(dxva_ctx->devmng, hd3ddev,
+ hr = IDirect3DDeviceManager9_GetVideoService(dxva_dev->devmng, hd3ddev,
&IID_IDirectXVideoDecoderService, &pv);
if (FAILED(hr)) {
ERR("GetVideoService failed\n");
return -1;
}
- dxva_ctx->vs = pv;
+ dxva_dev->vs = pv;
return 0;
}
/**
* Find the best suited decoder mode GUID and render format.
*/
-static int DxFindVideoServiceConversion(int codec_id)
+static int DxFindVideoServiceConversion(DXVAPluginContext *dxva_ctx, int codec_id)
{
unsigned i = 0;
GUID *guid_decdev = &dxva_ctx->guid_decdev;
/* Retreive supported modes from the decoder service */
UINT decdev_count = 0;
GUID *guid_decdev_list = NULL;
- if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(dxva_ctx->vs,
+ if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(dxva_dev->vs,
&decdev_count,
&guid_decdev_list))) {
ERR("IDirectXVideoDecoderService_GetDecoderDeviceGuids failed\n");
INFO("Trying to use '%s' as input\n", mode->name);
UINT render_fmt_count = 0;
D3DFORMAT *render_fmt_list = NULL;
- if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(dxva_ctx->vs, mode->guid,
+ if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(dxva_dev->vs, mode->guid,
&render_fmt_count,
&render_fmt_list))) {
ERR("IDirectXVideoDecoderService_GetDecoderRenderTargets failed\n");
return -1;
}
-static void DxDestroyVideoDecoder(void)
+static void DxDestroyVideoDecoder(DXVAPluginContext *dxva_ctx)
{
unsigned i = 0;
/**
* It creates a DXVA2 decoder using the given video format
*/
-static int DxCreateVideoDecoder(AVCodecContext *dec_ctx)
+static int DxCreateVideoDecoder(DXVAPluginContext *dxva_ctx, AVCodecContext *dec_ctx)
{
int surface_count = 0;
unsigned i = 0;
if (surface_count > VA_DXVA2_MAX_SURFACE_COUNT)
return -1;
dxva_ctx->surface_count = surface_count;
- if (FAILED(IDirectXVideoDecoderService_CreateSurface(dxva_ctx->vs,
+ if (FAILED(IDirectXVideoDecoderService_CreateSurface(dxva_dev->vs,
dxva_ctx->surface_width,
dxva_ctx->surface_height,
dxva_ctx->surface_count - 1,
dxva_ctx->surface_count = 0;
return -1;
}
+
+ dxva_ctx->surface = g_malloc_n(dxva_ctx->surface_count, sizeof(DXVAPluginSurface));
for (i = 0; i < dxva_ctx->surface_count; i++) {
- DXVAPluginSurface *surface = &dxva_ctx->surface[i];
- surface->d3d = dxva_ctx->hw_surface[i];
- surface->is_occupied = false;
+ dxva_ctx->surface[i].d3d = dxva_ctx->hw_surface[i];
+ dxva_ctx->surface[i].is_occupied = false;
+ dxva_ctx->surface[i].dxva_ctx = dxva_ctx;
}
TRACE("IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)\n",
dxva_ctx->surface_count, width, height);
/* List all configurations available for the decoder */
UINT cfg_count = 0;
DXVA2_ConfigPictureDecode *cfg_list = NULL;
- if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(dxva_ctx->vs,
+ if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(dxva_dev->vs,
&dxva_ctx->guid_decdev,
&dsc,
NULL,
/* Create the decoder */
IDirectXVideoDecoder *decoder;
- if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(dxva_ctx->vs,
+ if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(dxva_dev->vs,
&dxva_ctx->guid_decdev,
&dsc,
&dxva_ctx->cfg,
return 0;
}
-static void DxCreateVideoConversion(void)
+static void DxCreateVideoConversion(DXVAPluginContext *dxva_ctx)
{
unsigned int output = dxva_ctx->render_fmt;
*/
static void DxDestroyVideoService(void)
{
- if (dxva_ctx->hd3ddev)
- IDirect3DDeviceManager9_CloseDeviceHandle(dxva_ctx->devmng, dxva_ctx->hd3ddev);
- if (dxva_ctx->vs)
- IDirectXVideoDecoderService_Release(dxva_ctx->vs);
+ if (dxva_dev->hd3ddev)
+ IDirect3DDeviceManager9_CloseDeviceHandle(dxva_dev->devmng, dxva_dev->hd3ddev);
+ if (dxva_dev->vs)
+ IDirectXVideoDecoderService_Release(dxva_dev->vs);
}
/**
*/
static void D3dDestroyDeviceManager(void)
{
- if (dxva_ctx->devmng)
- IDirect3DDeviceManager9_Release(dxva_ctx->devmng);
+ if (dxva_dev->devmng)
+ IDirect3DDeviceManager9_Release(dxva_dev->devmng);
}
/**
*/
static void D3dDestroyDevice(void)
{
- if (dxva_ctx->d3ddev)
- IDirect3DDevice9_Release(dxva_ctx->d3ddev);
- if (dxva_ctx->d3dobj)
- IDirect3D9_Release(dxva_ctx->d3dobj);
+ if (dxva_dev->d3ddev)
+ IDirect3DDevice9_Release(dxva_dev->d3ddev);
+ if (dxva_dev->d3dobj)
+ IDirect3D9_Release(dxva_dev->d3dobj);
}
#if 0
static void maru_dxva2_close(void)
{
- DxDestroyVideoDecoder();
DxDestroyVideoService();
D3dDestroyDeviceManager();
D3dDestroyDevice();
- if (hdxva2_dll) {
- FreeLibrary(hdxva2_dll);
- hdxva2_dll = NULL;
- }
- if (hd3d9_dll) {
- FreeLibrary(hd3d9_dll);
- hd3d9_dll = NULL;
+ if (dxva_dev->hdxva2_dll) {
+ FreeLibrary(dxva_dev->hdxva2_dll);
+ dxva_dev->hdxva2_dll = NULL;
}
-
- if (dxva_ctx->hw_context) {
- free(dxva_ctx->hw_context);
- dxva_ctx->hw_context = NULL;
+ if (dxva_dev->hd3d9_dll) {
+ FreeLibrary(dxva_dev->hd3d9_dll);
+ dxva_dev->hd3d9_dll = NULL;
}
-
- //free(dxva_ctx);
}
static bool probe(void)
{
- if (hd3d9_dll == NULL || hdxva2_dll == NULL) {
- hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
- if (!hd3d9_dll) {
+ if (dxva_dev->hd3d9_dll == NULL || dxva_dev->hdxva2_dll == NULL) {
+ dxva_dev->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
+ if (!dxva_dev->hd3d9_dll) {
ERR("cannot load d3d9.dll\n");
goto error;
}
- hdxva2_dll = LoadLibrary(TEXT("DXVA2.DLL"));
- if (!hdxva2_dll) {
+ dxva_dev->hdxva2_dll = LoadLibrary(TEXT("DXVA2.DLL"));
+ if (!dxva_dev->hdxva2_dll) {
ERR("cannot load dxva2.dll\n");
goto error;
}
return false;
}
+static void cleanup(void *opaque)
+{
+ DXVAPluginContext *dxva_ctx = (DXVAPluginContext *)opaque;
+
+ DxDestroyVideoDecoder(dxva_ctx);
+
+ if (dxva_ctx->hw_context) {
+ g_free(dxva_ctx->hw_context);
+ }
+
+ g_free(dxva_ctx);
+
+}
+
static void *dxva_setup(AVCodecContext *dec_ctx, int width, int height)
{
- if (DxFindVideoServiceConversion(dec_ctx->codec_id)) {
+ DXVAPluginContext *dxva_ctx = g_malloc0(sizeof(DXVAPluginContext));
+
+ if (DxFindVideoServiceConversion(dxva_ctx, dec_ctx->codec_id)) {
ERR("DxFindVideoServiceConversion failed\n");
return NULL;
}
dxva_ctx->thread_count = dec_ctx->thread_count;
- //TODO: destroy surface and decoder at avcontext deinit()
- DxDestroyVideoDecoder();
-
- if (DxCreateVideoDecoder(dec_ctx) < -1) {
+ if (DxCreateVideoDecoder(dxva_ctx, dec_ctx) < -1) {
ERR("DxCreateVideoDecoder failed\n");
return NULL;
}
dxva_ctx->hw_context->surface_count = dxva_ctx->surface_count;
dxva_ctx->hw_context->surface = dxva_ctx->hw_surface;
- DxCreateVideoConversion();
+ DxCreateVideoConversion(dxva_ctx);
return dxva_ctx;
}
{
unsigned i = 0;
DXVAPluginSurface *surface = NULL;
+ DXVAPluginContext *dxva_ctx = (DXVAPluginContext *)get_plugin_context(dec_ctx);
/* Check the device */
#if 0
- HRESULT hr = IDirect3DDeviceManager9_TestDevice(dxva_ctx->devmng, dxva_ctx->hd3ddev);
+ HRESULT hr = IDirect3DDeviceManager9_TestDevice(dxva_dev->devmng, dxva_dev->hd3ddev);
if (hr == DXVA2_E_NEW_VIDEO_DEVICE) {
if (DxResetVideoDecoder())
return -1;
{
AVFrame *frame = (AVFrame *)src;
LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)frame->data[3];
+ DXVAPluginContext *dxva_ctx = (DXVAPluginContext *)((DXVAPluginSurface *)frame->opaque)->dxva_ctx;
/* */
assert(dxva_ctx->output == MAKEFOURCC('Y','V','1','2'));
.output_pix_fmt = PIX_FMT_YUV420P,
.probe = probe,
.setup = dxva_setup,
+ .cleanup = cleanup,
.get_buffer = dxva_get_surface,
.release_buffer = dxva_release_surface,
.get_picture = extract,