Commit 4db3b62d authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

DxVA2: remove vlc_object_t back pointer

parent f1457ea3
...@@ -240,7 +240,6 @@ typedef struct { ...@@ -240,7 +240,6 @@ typedef struct {
#define VA_DXVA2_MAX_SURFACE_COUNT (64) #define VA_DXVA2_MAX_SURFACE_COUNT (64)
struct vlc_va_sys_t struct vlc_va_sys_t
{ {
vlc_object_t *log;
int codec_id; int codec_id;
int width; int width;
int height; int height;
...@@ -288,48 +287,39 @@ struct vlc_va_sys_t ...@@ -288,48 +287,39 @@ struct vlc_va_sys_t
vlc_va_surface_t surface[VA_DXVA2_MAX_SURFACE_COUNT]; vlc_va_surface_t surface[VA_DXVA2_MAX_SURFACE_COUNT];
LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT]; LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
}; };
typedef struct vlc_va_sys_t vlc_va_dxva2_t;
/* */ /* */
static vlc_va_dxva2_t *vlc_va_dxva2_Get(vlc_va_t *external) static int D3dCreateDevice(vlc_va_t *);
{ static void D3dDestroyDevice(vlc_va_sys_t *);
vlc_va_dxva2_t *va = external->sys; static char *DxDescribe(vlc_va_sys_t *);
assert(VLC_OBJECT(external) == va->log);
return va;
}
/* */
static int D3dCreateDevice(vlc_va_dxva2_t *);
static void D3dDestroyDevice(vlc_va_dxva2_t *);
static char *DxDescribe(vlc_va_dxva2_t *);
static int D3dCreateDeviceManager(vlc_va_dxva2_t *); static int D3dCreateDeviceManager(vlc_va_t *);
static void D3dDestroyDeviceManager(vlc_va_dxva2_t *); static void D3dDestroyDeviceManager(vlc_va_sys_t *);
static int DxCreateVideoService(vlc_va_dxva2_t *); static int DxCreateVideoService(vlc_va_t *);
static void DxDestroyVideoService(vlc_va_dxva2_t *); static void DxDestroyVideoService(vlc_va_sys_t *);
static int DxFindVideoServiceConversion(vlc_va_dxva2_t *, GUID *input, D3DFORMAT *output); static int DxFindVideoServiceConversion(vlc_va_t *, GUID *input, D3DFORMAT *output);
static int DxCreateVideoDecoder(vlc_va_dxva2_t *, static int DxCreateVideoDecoder(vlc_va_t *,
int codec_id, const video_format_t *); int codec_id, const video_format_t *);
static void DxDestroyVideoDecoder(vlc_va_dxva2_t *); static void DxDestroyVideoDecoder(vlc_va_sys_t *);
static int DxResetVideoDecoder(vlc_va_dxva2_t *); static int DxResetVideoDecoder(vlc_va_t *);
static void DxCreateVideoConversion(vlc_va_dxva2_t *); static void DxCreateVideoConversion(vlc_va_sys_t *);
static void DxDestroyVideoConversion(vlc_va_dxva2_t *); static void DxDestroyVideoConversion(vlc_va_sys_t *);
/* */ /* */
static int Setup(vlc_va_t *external, void **hw, vlc_fourcc_t *chroma, static int Setup(vlc_va_t *va, void **hw, vlc_fourcc_t *chroma,
int width, int height) int width, int height)
{ {
vlc_va_dxva2_t *va = vlc_va_dxva2_Get(external); vlc_va_sys_t *sys = va->sys;
if (va->width == width && va->height == height && va->decoder) if (sys->width == width && sys->height == height && sys->decoder)
goto ok; goto ok;
/* */ /* */
DxDestroyVideoConversion(va); DxDestroyVideoConversion(sys);
DxDestroyVideoDecoder(va); DxDestroyVideoDecoder(sys);
*hw = NULL; *hw = NULL;
*chroma = 0; *chroma = 0;
...@@ -342,48 +332,48 @@ static int Setup(vlc_va_t *external, void **hw, vlc_fourcc_t *chroma, ...@@ -342,48 +332,48 @@ static int Setup(vlc_va_t *external, void **hw, vlc_fourcc_t *chroma,
fmt.i_width = width; fmt.i_width = width;
fmt.i_height = height; fmt.i_height = height;
if (DxCreateVideoDecoder(va, va->codec_id, &fmt)) if (DxCreateVideoDecoder(va, sys->codec_id, &fmt))
return VLC_EGENERIC; return VLC_EGENERIC;
/* */ /* */
va->hw.decoder = va->decoder; sys->hw.decoder = sys->decoder;
va->hw.cfg = &va->cfg; sys->hw.cfg = &sys->cfg;
va->hw.surface_count = va->surface_count; sys->hw.surface_count = sys->surface_count;
va->hw.surface = va->hw_surface; sys->hw.surface = sys->hw_surface;
/* */ /* */
DxCreateVideoConversion(va); DxCreateVideoConversion(sys);
/* */ /* */
ok: ok:
*hw = &va->hw; *hw = &sys->hw;
const d3d_format_t *output = D3dFindFormat(va->output); const d3d_format_t *output = D3dFindFormat(sys->output);
*chroma = output->codec; *chroma = output->codec;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int Extract(vlc_va_t *external, picture_t *picture, void *opaque, static int Extract(vlc_va_t *va, picture_t *picture, void *opaque,
uint8_t *data) uint8_t *data)
{ {
vlc_va_dxva2_t *va = vlc_va_dxva2_Get(external); vlc_va_sys_t *sys = va->sys;
LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)data; LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)data;
if (!va->surface_cache.buffer) if (!sys->surface_cache.buffer)
return VLC_EGENERIC; return VLC_EGENERIC;
/* */ /* */
assert(va->output == MAKEFOURCC('Y','V','1','2')); assert(sys->output == MAKEFOURCC('Y','V','1','2'));
/* */ /* */
D3DLOCKED_RECT lock; D3DLOCKED_RECT lock;
if (FAILED(IDirect3DSurface9_LockRect(d3d, &lock, NULL, D3DLOCK_READONLY))) { if (FAILED(IDirect3DSurface9_LockRect(d3d, &lock, NULL, D3DLOCK_READONLY))) {
msg_Err(va->log, "Failed to lock surface"); msg_Err(va, "Failed to lock surface");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
if (va->render == MAKEFOURCC('Y','V','1','2') || if (sys->render == MAKEFOURCC('Y','V','1','2') ||
va->render == MAKEFOURCC('I','M','C','3')) { sys->render == MAKEFOURCC('I','M','C','3')) {
bool imc3 = va->render == MAKEFOURCC('I','M','C','3'); bool imc3 = sys->render == MAKEFOURCC('I','M','C','3');
size_t chroma_pitch = imc3 ? lock.Pitch : (lock.Pitch / 2); size_t chroma_pitch = imc3 ? lock.Pitch : (lock.Pitch / 2);
size_t pitch[3] = { size_t pitch[3] = {
...@@ -394,9 +384,9 @@ static int Extract(vlc_va_t *external, picture_t *picture, void *opaque, ...@@ -394,9 +384,9 @@ static int Extract(vlc_va_t *external, picture_t *picture, void *opaque,
uint8_t *plane[3] = { uint8_t *plane[3] = {
(uint8_t*)lock.pBits, (uint8_t*)lock.pBits,
(uint8_t*)lock.pBits + pitch[0] * va->surface_height, (uint8_t*)lock.pBits + pitch[0] * sys->surface_height,
(uint8_t*)lock.pBits + pitch[0] * va->surface_height (uint8_t*)lock.pBits + pitch[0] * sys->surface_height
+ pitch[1] * va->surface_height / 2, + pitch[1] * sys->surface_height / 2,
}; };
if (imc3) { if (imc3) {
...@@ -404,22 +394,20 @@ static int Extract(vlc_va_t *external, picture_t *picture, void *opaque, ...@@ -404,22 +394,20 @@ static int Extract(vlc_va_t *external, picture_t *picture, void *opaque,
plane[1] = plane[2]; plane[1] = plane[2];
plane[2] = V; plane[2] = V;
} }
CopyFromYv12(picture, plane, pitch, CopyFromYv12(picture, plane, pitch, sys->width, sys->height,
va->width, va->height, &sys->surface_cache);
&va->surface_cache);
} else { } else {
assert(va->render == MAKEFOURCC('N','V','1','2')); assert(sys->render == MAKEFOURCC('N','V','1','2'));
uint8_t *plane[2] = { uint8_t *plane[2] = {
lock.pBits, lock.pBits,
(uint8_t*)lock.pBits + lock.Pitch * va->surface_height (uint8_t*)lock.pBits + lock.Pitch * sys->surface_height
}; };
size_t pitch[2] = { size_t pitch[2] = {
lock.Pitch, lock.Pitch,
lock.Pitch, lock.Pitch,
}; };
CopyFromNv12(picture, plane, pitch, CopyFromNv12(picture, plane, pitch, sys->width, sys->height,
va->width, va->height, &sys->surface_cache);
&va->surface_cache);
} }
/* */ /* */
...@@ -429,39 +417,39 @@ static int Extract(vlc_va_t *external, picture_t *picture, void *opaque, ...@@ -429,39 +417,39 @@ static int Extract(vlc_va_t *external, picture_t *picture, void *opaque,
} }
/* FIXME it is nearly common with VAAPI */ /* FIXME it is nearly common with VAAPI */
static int Get(vlc_va_t *external, void **opaque, uint8_t **data) static int Get(vlc_va_t *va, void **opaque, uint8_t **data)
{ {
vlc_va_dxva2_t *va = vlc_va_dxva2_Get(external); vlc_va_sys_t *sys = va->sys;
/* Check the device */ /* Check the device */
HRESULT hr = IDirect3DDeviceManager9_TestDevice(va->devmng, va->device); HRESULT hr = IDirect3DDeviceManager9_TestDevice(sys->devmng, sys->device);
if (hr == DXVA2_E_NEW_VIDEO_DEVICE) { if (hr == DXVA2_E_NEW_VIDEO_DEVICE) {
if (DxResetVideoDecoder(va)) if (DxResetVideoDecoder(va))
return VLC_EGENERIC; return VLC_EGENERIC;
} else if (FAILED(hr)) { } else if (FAILED(hr)) {
msg_Err(va->log, "IDirect3DDeviceManager9_TestDevice %u", (unsigned)hr); msg_Err(va, "IDirect3DDeviceManager9_TestDevice %u", (unsigned)hr);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* Grab an unused surface, in case none are, try the oldest /* Grab an unused surface, in case none are, try the oldest
* XXX using the oldest is a workaround in case a problem happens with libavcodec */ * XXX using the oldest is a workaround in case a problem happens with libavcodec */
unsigned i, old; unsigned i, old;
for (i = 0, old = 0; i < va->surface_count; i++) { for (i = 0, old = 0; i < sys->surface_count; i++) {
vlc_va_surface_t *surface = &va->surface[i]; vlc_va_surface_t *surface = &sys->surface[i];
if (!surface->refcount) if (!surface->refcount)
break; break;
if (surface->order < va->surface[old].order) if (surface->order < sys->surface[old].order)
old = i; old = i;
} }
if (i >= va->surface_count) if (i >= sys->surface_count)
i = old; i = old;
vlc_va_surface_t *surface = &va->surface[i]; vlc_va_surface_t *surface = &sys->surface[i];
surface->refcount = 1; surface->refcount = 1;
surface->order = va->surface_order++; surface->order = sys->surface_order++;
*data = (void *)surface->d3d; *data = (void *)surface->d3d;
*opaque = surface; *opaque = surface;
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -475,87 +463,84 @@ static void Release(void *opaque, uint8_t *data) ...@@ -475,87 +463,84 @@ static void Release(void *opaque, uint8_t *data)
(void) data; (void) data;
} }
static void Close(vlc_va_t *external) static void Close(vlc_va_t *va)
{ {
vlc_va_dxva2_t *va = vlc_va_dxva2_Get(external); vlc_va_sys_t *sys = va->sys;
DxDestroyVideoConversion(va); DxDestroyVideoConversion(sys);
DxDestroyVideoDecoder(va); DxDestroyVideoDecoder(sys);
DxDestroyVideoService(va); DxDestroyVideoService(sys);
D3dDestroyDeviceManager(va); D3dDestroyDeviceManager(sys);
D3dDestroyDevice(va); D3dDestroyDevice(sys);
if (va->hdxva2_dll) if (sys->hdxva2_dll)
FreeLibrary(va->hdxva2_dll); FreeLibrary(sys->hdxva2_dll);
if (va->hd3d9_dll) if (sys->hd3d9_dll)
FreeLibrary(va->hd3d9_dll); FreeLibrary(sys->hd3d9_dll);
free(external->description); free(va->description);
free(va); free(sys);
} }
static int Open(vlc_va_t *external, AVCodecContext *ctx, static int Open(vlc_va_t *va, AVCodecContext *ctx, const es_format_t *fmt)
const es_format_t *fmt)
{ {
vlc_va_dxva2_t *va = calloc(1, sizeof(*va)); vlc_va_sys_t *sys = calloc(1, sizeof (*sys));
if (!va) if (unlikely(sys == NULL))
return VLC_EGENERIC; return VLC_ENOMEM;
external->sys = va; va->sys = sys;
/* */ sys->codec_id = ctx->codec_id;
va->log = VLC_OBJECT(external);
va->codec_id = ctx->codec_id;
(void) fmt; (void) fmt;
/* Load dll*/ /* Load dll*/
va->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL")); sys->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
if (!va->hd3d9_dll) { if (!sys->hd3d9_dll) {
msg_Warn(va->log, "cannot load d3d9.dll"); msg_Warn(va, "cannot load d3d9.dll");
goto error; goto error;
} }
va->hdxva2_dll = LoadLibrary(TEXT("DXVA2.DLL")); sys->hdxva2_dll = LoadLibrary(TEXT("DXVA2.DLL"));
if (!va->hdxva2_dll) { if (!sys->hdxva2_dll) {
msg_Warn(va->log, "cannot load dxva2.dll"); msg_Warn(va, "cannot load dxva2.dll");
goto error; goto error;
} }
msg_Dbg(va->log, "DLLs loaded"); msg_Dbg(va, "DLLs loaded");
/* */ /* */
if (D3dCreateDevice(va)) { if (D3dCreateDevice(va)) {
msg_Err(va->log, "Failed to create Direct3D device"); msg_Err(va, "Failed to create Direct3D device");
goto error; goto error;
} }
msg_Dbg(va->log, "D3dCreateDevice succeed"); msg_Dbg(va, "D3dCreateDevice succeed");
if (D3dCreateDeviceManager(va)) { if (D3dCreateDeviceManager(va)) {
msg_Err(va->log, "D3dCreateDeviceManager failed"); msg_Err(va, "D3dCreateDeviceManager failed");
goto error; goto error;
} }
if (DxCreateVideoService(va)) { if (DxCreateVideoService(va)) {
msg_Err(va->log, "DxCreateVideoService failed"); msg_Err(va, "DxCreateVideoService failed");
goto error; goto error;
} }
/* */ /* */
if (DxFindVideoServiceConversion(va, &va->input, &va->render)) { if (DxFindVideoServiceConversion(va, &sys->input, &sys->render)) {
msg_Err(va->log, "DxFindVideoServiceConversion failed"); msg_Err(va, "DxFindVideoServiceConversion failed");
goto error; goto error;
} }
va->thread_count = ctx->thread_count; sys->thread_count = ctx->thread_count;
/* TODO print the hardware name/vendor for debugging purposes */ /* TODO print the hardware name/vendor for debugging purposes */
external->description = DxDescribe(va); va->description = DxDescribe(sys);
external->pix_fmt = PIX_FMT_DXVA2_VLD; va->pix_fmt = PIX_FMT_DXVA2_VLD;
external->setup = Setup; va->setup = Setup;
external->get = Get; va->get = Get;
external->release = Release; va->release = Release;
external->extract = Extract; va->extract = Extract;
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
Close(external); Close(va);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* */ /* */
...@@ -563,14 +548,15 @@ error: ...@@ -563,14 +548,15 @@ error:
/** /**
* It creates a Direct3D device usable for DXVA 2 * It creates a Direct3D device usable for DXVA 2
*/ */
static int D3dCreateDevice(vlc_va_dxva2_t *va) static int D3dCreateDevice(vlc_va_t *va)
{ {
vlc_va_sys_t *sys = va->sys;
/* */ /* */
LPDIRECT3D9 (WINAPI *Create9)(UINT SDKVersion); LPDIRECT3D9 (WINAPI *Create9)(UINT SDKVersion);
Create9 = (void *)GetProcAddress(va->hd3d9_dll, Create9 = (void *)GetProcAddress(sys->hd3d9_dll, "Direct3DCreate9");
"Direct3DCreate9");
if (!Create9) { if (!Create9) {
msg_Err(va->log, "Cannot locate reference to Direct3DCreate9 ABI in DLL"); msg_Err(va, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -578,21 +564,21 @@ static int D3dCreateDevice(vlc_va_dxva2_t *va) ...@@ -578,21 +564,21 @@ static int D3dCreateDevice(vlc_va_dxva2_t *va)
LPDIRECT3D9 d3dobj; LPDIRECT3D9 d3dobj;
d3dobj = Create9(D3D_SDK_VERSION); d3dobj = Create9(D3D_SDK_VERSION);
if (!d3dobj) { if (!d3dobj) {
msg_Err(va->log, "Direct3DCreate9 failed"); msg_Err(va, "Direct3DCreate9 failed");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
va->d3dobj = d3dobj; sys->d3dobj = d3dobj;
/* */ /* */
D3DADAPTER_IDENTIFIER9 *d3dai = &va->d3dai; D3DADAPTER_IDENTIFIER9 *d3dai = &sys->d3dai;
if (FAILED(IDirect3D9_GetAdapterIdentifier(va->d3dobj, if (FAILED(IDirect3D9_GetAdapterIdentifier(sys->d3dobj,
D3DADAPTER_DEFAULT, 0, d3dai))) { D3DADAPTER_DEFAULT, 0, d3dai))) {
msg_Warn(va->log, "IDirect3D9_GetAdapterIdentifier failed"); msg_Warn(va, "IDirect3D9_GetAdapterIdentifier failed");
ZeroMemory(d3dai, sizeof(*d3dai)); ZeroMemory(d3dai, sizeof(*d3dai));
} }
/* */ /* */
D3DPRESENT_PARAMETERS *d3dpp = &va->d3dpp; D3DPRESENT_PARAMETERS *d3dpp = &sys->d3dpp;
ZeroMemory(d3dpp, sizeof(*d3dpp)); ZeroMemory(d3dpp, sizeof(*d3dpp));
d3dpp->Flags = D3DPRESENTFLAG_VIDEO; d3dpp->Flags = D3DPRESENTFLAG_VIDEO;
d3dpp->Windowed = TRUE; d3dpp->Windowed = TRUE;
...@@ -615,17 +601,18 @@ static int D3dCreateDevice(vlc_va_dxva2_t *va) ...@@ -615,17 +601,18 @@ static int D3dCreateDevice(vlc_va_dxva2_t *va)
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING |
D3DCREATE_MULTITHREADED, D3DCREATE_MULTITHREADED,
d3dpp, &d3ddev))) { d3dpp, &d3ddev))) {
msg_Err(va->log, "IDirect3D9_CreateDevice failed"); msg_Err(va, "IDirect3D9_CreateDevice failed");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
va->d3ddev = d3ddev; sys->d3ddev = d3ddev;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/** /**
* It releases a Direct3D device and its resources. * It releases a Direct3D device and its resources.
*/ */
static void D3dDestroyDevice(vlc_va_dxva2_t *va) static void D3dDestroyDevice(vlc_va_sys_t *va)
{ {
if (va->d3ddev) if (va->d3ddev)
IDirect3DDevice9_Release(va->d3ddev); IDirect3DDevice9_Release(va->d3ddev);
...@@ -635,7 +622,7 @@ static void D3dDestroyDevice(vlc_va_dxva2_t *va) ...@@ -635,7 +622,7 @@ static void D3dDestroyDevice(vlc_va_dxva2_t *va)
/** /**
* It describes our Direct3D object * It describes our Direct3D object
*/ */
static char *DxDescribe(vlc_va_dxva2_t *va) static char *DxDescribe(vlc_va_sys_t *va)
{ {
static const struct { static const struct {
unsigned id; unsigned id;
...@@ -669,33 +656,35 @@ static char *DxDescribe(vlc_va_dxva2_t *va) ...@@ -669,33 +656,35 @@ static char *DxDescribe(vlc_va_dxva2_t *va)
/** /**
* It creates a Direct3D device manager * It creates a Direct3D device manager
*/ */
static int D3dCreateDeviceManager(vlc_va_dxva2_t *va) static int D3dCreateDeviceManager(vlc_va_t *va)
{ {
vlc_va_sys_t *sys = va->sys;
HRESULT (WINAPI *CreateDeviceManager9)(UINT *pResetToken, HRESULT (WINAPI *CreateDeviceManager9)(UINT *pResetToken,
IDirect3DDeviceManager9 **); IDirect3DDeviceManager9 **);
CreateDeviceManager9 = CreateDeviceManager9 =
(void *)GetProcAddress(va->hdxva2_dll, (void *)GetProcAddress(sys->hdxva2_dll,
"DXVA2CreateDirect3DDeviceManager9"); "DXVA2CreateDirect3DDeviceManager9");
if (!CreateDeviceManager9) { if (!CreateDeviceManager9) {
msg_Err(va->log, "cannot load function"); msg_Err(va, "cannot load function");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
msg_Dbg(va->log, "OurDirect3DCreateDeviceManager9 Success!"); msg_Dbg(va, "OurDirect3DCreateDeviceManager9 Success!");
UINT token; UINT token;
IDirect3DDeviceManager9 *devmng; IDirect3DDeviceManager9 *devmng;
if (FAILED(CreateDeviceManager9(&token, &devmng))) { if (FAILED(CreateDeviceManager9(&token, &devmng))) {
msg_Err(va->log, " OurDirect3DCreateDeviceManager9 failed"); msg_Err(va, " OurDirect3DCreateDeviceManager9 failed");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
va->token = token; sys->token = token;
va->devmng = devmng; sys->devmng = devmng;
msg_Info(va->log, "obtained IDirect3DDeviceManager9"); msg_Info(va, "obtained IDirect3DDeviceManager9");
HRESULT hr = IDirect3DDeviceManager9_ResetDevice(devmng, va->d3ddev, token); HRESULT hr = IDirect3DDeviceManager9_ResetDevice(devmng, sys->d3ddev, token);
if (FAILED(hr)) { if (FAILED(hr)) {
msg_Err(va->log, "IDirect3DDeviceManager9_ResetDevice failed: %08x", (unsigned)hr); msg_Err(va, "IDirect3DDeviceManager9_ResetDevice failed: %08x", (unsigned)hr);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -703,7 +692,7 @@ static int D3dCreateDeviceManager(vlc_va_dxva2_t *va) ...@@ -703,7 +692,7 @@ static int D3dCreateDeviceManager(vlc_va_dxva2_t *va)
/** /**
* It destroys a Direct3D device manager * It destroys a Direct3D device manager
*/ */
static void D3dDestroyDeviceManager(vlc_va_dxva2_t *va) static void D3dDestroyDeviceManager(vlc_va_sys_t *va)
{ {
if (va->devmng) if (va->devmng)
IDirect3DDeviceManager9_Release(va->devmng); IDirect3DDeviceManager9_Release(va->devmng);
...@@ -712,47 +701,48 @@ static void D3dDestroyDeviceManager(vlc_va_dxva2_t *va) ...@@ -712,47 +701,48 @@ static void D3dDestroyDeviceManager(vlc_va_dxva2_t *va)
/** /**
* It creates a DirectX video service * It creates a DirectX video service
*/ */
static int DxCreateVideoService(vlc_va_dxva2_t *va) static int DxCreateVideoService(vlc_va_t *va)
{ {
vlc_va_sys_t *sys = va->sys;
HRESULT (WINAPI *CreateVideoService)(IDirect3DDevice9 *, HRESULT (WINAPI *CreateVideoService)(IDirect3DDevice9 *,
REFIID riid, REFIID riid,
void **ppService); void **ppService);
CreateVideoService = CreateVideoService =
(void *)GetProcAddress(va->hdxva2_dll, (void *)GetProcAddress(sys->hdxva2_dll, "DXVA2CreateVideoService");
"DXVA2CreateVideoService");
if (!CreateVideoService) { if (!CreateVideoService) {
msg_Err(va->log, "cannot load function"); msg_Err(va, "cannot load function");
return 4; return 4;
} }
msg_Info(va->log, "DXVA2CreateVideoService Success!"); msg_Info(va, "DXVA2CreateVideoService Success!");
HRESULT hr; HRESULT hr;
HANDLE device; HANDLE device;
hr = IDirect3DDeviceManager9_OpenDeviceHandle(va->devmng, &device); hr = IDirect3DDeviceManager9_OpenDeviceHandle(sys->devmng, &device);
if (FAILED(hr)) { if (FAILED(hr)) {
msg_Err(va->log, "OpenDeviceHandle failed"); msg_Err(va, "OpenDeviceHandle failed");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
va->device = device; sys->device = device;
IDirectXVideoDecoderService *vs; void *pv;
hr = IDirect3DDeviceManager9_GetVideoService(va->devmng, device, hr = IDirect3DDeviceManager9_GetVideoService(sys->devmng, device,
&IID_IDirectXVideoDecoderService, &IID_IDirectXVideoDecoderService, &pv);
(void**)&vs);
if (FAILED(hr)) { if (FAILED(hr)) {
msg_Err(va->log, "GetVideoService failed"); msg_Err(va, "GetVideoService failed");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
va->vs = vs; sys->vs = pv;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/** /**
* It destroys a DirectX video service * It destroys a DirectX video service
*/ */
static void DxDestroyVideoService(vlc_va_dxva2_t *va) static void DxDestroyVideoService(vlc_va_sys_t *va)
{ {
if (va->device) if (va->device)
IDirect3DDeviceManager9_CloseDeviceHandle(va->devmng, va->device); IDirect3DDeviceManager9_CloseDeviceHandle(va->devmng, va->device);
...@@ -762,24 +752,26 @@ static void DxDestroyVideoService(vlc_va_dxva2_t *va) ...@@ -762,24 +752,26 @@ static void DxDestroyVideoService(vlc_va_dxva2_t *va)
/** /**
* Find the best suited decoder mode GUID and render format. * Find the best suited decoder mode GUID and render format.
*/ */
static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORMAT *output) static int DxFindVideoServiceConversion(vlc_va_t *va, GUID *input, D3DFORMAT *output)
{ {
vlc_va_sys_t *sys = va->sys;
/* Retreive supported modes from the decoder service */ /* Retreive supported modes from the decoder service */
UINT input_count = 0; UINT input_count = 0;
GUID *input_list = NULL; GUID *input_list = NULL;
if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(va->vs, if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids(sys->vs,
&input_count, &input_count,
&input_list))) { &input_list))) {
msg_Err(va->log, "IDirectXVideoDecoderService_GetDecoderDeviceGuids failed"); msg_Err(va, "IDirectXVideoDecoderService_GetDecoderDeviceGuids failed");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
for (unsigned i = 0; i < input_count; i++) { for (unsigned i = 0; i < input_count; i++) {
const GUID *g = &input_list[i]; const GUID *g = &input_list[i];
const dxva2_mode_t *mode = Dxva2FindMode(g); const dxva2_mode_t *mode = Dxva2FindMode(g);
if (mode) { if (mode) {
msg_Dbg(va->log, "- '%s' is supported by hardware", mode->name); msg_Dbg(va, "- '%s' is supported by hardware", mode->name);
} else { } else {
msg_Warn(va->log, "- Unknown GUID = %08X-%04x-%04x-XXXX", msg_Warn(va, "- Unknown GUID = %08X-%04x-%04x-XXXX",
(unsigned)g->Data1, g->Data2, g->Data3); (unsigned)g->Data1, g->Data2, g->Data3);
} }
} }
...@@ -787,7 +779,7 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM ...@@ -787,7 +779,7 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM
/* Try all supported mode by our priority */ /* Try all supported mode by our priority */
for (unsigned i = 0; dxva2_modes[i].name; i++) { for (unsigned i = 0; dxva2_modes[i].name; i++) {
const dxva2_mode_t *mode = &dxva2_modes[i]; const dxva2_mode_t *mode = &dxva2_modes[i];
if (!mode->codec || mode->codec != va->codec_id) if (!mode->codec || mode->codec != sys->codec_id)
continue; continue;
/* */ /* */
...@@ -799,22 +791,22 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM ...@@ -799,22 +791,22 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM
continue; continue;
/* */ /* */
msg_Dbg(va->log, "Trying to use '%s' as input", mode->name); msg_Dbg(va, "Trying to use '%s' as input", mode->name);
UINT output_count = 0; UINT output_count = 0;
D3DFORMAT *output_list = NULL; D3DFORMAT *output_list = NULL;
if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(va->vs, mode->guid, if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets(sys->vs, mode->guid,
&output_count, &output_count,
&output_list))) { &output_list))) {
msg_Err(va->log, "IDirectXVideoDecoderService_GetDecoderRenderTargets failed"); msg_Err(va, "IDirectXVideoDecoderService_GetDecoderRenderTargets failed");
continue; continue;
} }
for (unsigned j = 0; j < output_count; j++) { for (unsigned j = 0; j < output_count; j++) {
const D3DFORMAT f = output_list[j]; const D3DFORMAT f = output_list[j];
const d3d_format_t *format = D3dFindFormat(f); const d3d_format_t *format = D3dFindFormat(f);
if (format) { if (format) {
msg_Dbg(va->log, "%s is supported for output", format->name); msg_Dbg(va, "%s is supported for output", format->name);
} else { } else {
msg_Dbg(va->log, "%d is supported for output (%4.4s)", f, (const char*)&f); msg_Dbg(va, "%d is supported for output (%4.4s)", f, (const char*)&f);
} }
} }
...@@ -831,7 +823,7 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM ...@@ -831,7 +823,7 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM
continue; continue;
/* We have our solution */ /* We have our solution */
msg_Dbg(va->log, "Using '%s' to decode to '%s'", mode->name, format->name); msg_Dbg(va, "Using '%s' to decode to '%s'", mode->name, format->name);
*input = *mode->guid; *input = *mode->guid;
*output = format->format; *output = format->format;
CoTaskMemFree(output_list); CoTaskMemFree(output_list);
...@@ -847,23 +839,25 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM ...@@ -847,23 +839,25 @@ static int DxFindVideoServiceConversion(vlc_va_dxva2_t *va, GUID *input, D3DFORM
/** /**
* It creates a DXVA2 decoder using the given video format * It creates a DXVA2 decoder using the given video format
*/ */
static int DxCreateVideoDecoder(vlc_va_dxva2_t *va, static int DxCreateVideoDecoder(vlc_va_t *va,
int codec_id, const video_format_t *fmt) int codec_id, const video_format_t *fmt)
{ {
vlc_va_sys_t *sys = va->sys;
/* */ /* */
msg_Dbg(va->log, "DxCreateVideoDecoder id %d %dx%d", msg_Dbg(va, "DxCreateVideoDecoder id %d %dx%d",
codec_id, fmt->i_width, fmt->i_height); codec_id, fmt->i_width, fmt->i_height);
va->width = fmt->i_width; sys->width = fmt->i_width;
va->height = fmt->i_height; sys->height = fmt->i_height;
/* Allocates all surfaces needed for the decoder */ /* Allocates all surfaces needed for the decoder */
va->surface_width = (fmt->i_width + 15) & ~15; sys->surface_width = (fmt->i_width + 15) & ~15;
va->surface_height = (fmt->i_height + 15) & ~15; sys->surface_height = (fmt->i_height + 15) & ~15;
int surface_count; int surface_count;
switch (codec_id) { switch (codec_id) {
case AV_CODEC_ID_H264: case AV_CODEC_ID_H264:
surface_count = 16 + va->thread_count + 2; surface_count = 16 + sys->thread_count + 2;
break; break;
case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG1VIDEO:
case AV_CODEC_ID_MPEG2VIDEO: case AV_CODEC_ID_MPEG2VIDEO:
...@@ -875,36 +869,36 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va, ...@@ -875,36 +869,36 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va,
} }
if (surface_count > VA_DXVA2_MAX_SURFACE_COUNT) if (surface_count > VA_DXVA2_MAX_SURFACE_COUNT)
return VLC_EGENERIC; return VLC_EGENERIC;
va->surface_count = surface_count; sys->surface_count = surface_count;
if (FAILED(IDirectXVideoDecoderService_CreateSurface(va->vs, if (FAILED(IDirectXVideoDecoderService_CreateSurface(sys->vs,
va->surface_width, sys->surface_width,
va->surface_height, sys->surface_height,
va->surface_count - 1, sys->surface_count - 1,
va->render, sys->render,
D3DPOOL_DEFAULT, D3DPOOL_DEFAULT,
0, 0,
DXVA2_VideoDecoderRenderTarget, DXVA2_VideoDecoderRenderTarget,
va->hw_surface, sys->hw_surface,
NULL))) { NULL))) {
msg_Err(va->log, "IDirectXVideoAccelerationService_CreateSurface failed"); msg_Err(va, "IDirectXVideoAccelerationService_CreateSurface failed");
va->surface_count = 0; sys->surface_count = 0;
return VLC_EGENERIC; return VLC_EGENERIC;
} }
for (unsigned i = 0; i < va->surface_count; i++) { for (unsigned i = 0; i < sys->surface_count; i++) {
vlc_va_surface_t *surface = &va->surface[i]; vlc_va_surface_t *surface = &sys->surface[i];
surface->d3d = va->hw_surface[i]; surface->d3d = sys->hw_surface[i];
surface->refcount = 0; surface->refcount = 0;
surface->order = 0; surface->order = 0;
} }
msg_Dbg(va->log, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)", msg_Dbg(va, "IDirectXVideoAccelerationService_CreateSurface succeed with %d surfaces (%dx%d)",
va->surface_count, fmt->i_width, fmt->i_height); sys->surface_count, fmt->i_width, fmt->i_height);
/* */ /* */
DXVA2_VideoDesc dsc; DXVA2_VideoDesc dsc;
ZeroMemory(&dsc, sizeof(dsc)); ZeroMemory(&dsc, sizeof(dsc));
dsc.SampleWidth = fmt->i_width; dsc.SampleWidth = fmt->i_width;
dsc.SampleHeight = fmt->i_height; dsc.SampleHeight = fmt->i_height;
dsc.Format = va->render; dsc.Format = sys->render;
if (fmt->i_frame_rate > 0 && fmt->i_frame_rate_base > 0) { if (fmt->i_frame_rate > 0 && fmt->i_frame_rate_base > 0) {
dsc.InputSampleFreq.Numerator = fmt->i_frame_rate; dsc.InputSampleFreq.Numerator = fmt->i_frame_rate;
dsc.InputSampleFreq.Denominator = fmt->i_frame_rate_base; dsc.InputSampleFreq.Denominator = fmt->i_frame_rate_base;
...@@ -929,16 +923,16 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va, ...@@ -929,16 +923,16 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va,
/* List all configurations available for the decoder */ /* List all configurations available for the decoder */
UINT cfg_count = 0; UINT cfg_count = 0;
DXVA2_ConfigPictureDecode *cfg_list = NULL; DXVA2_ConfigPictureDecode *cfg_list = NULL;
if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(va->vs, if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations(sys->vs,
&va->input, &sys->input,
&dsc, &dsc,
NULL, NULL,
&cfg_count, &cfg_count,
&cfg_list))) { &cfg_list))) {
msg_Err(va->log, "IDirectXVideoDecoderService_GetDecoderConfigurations failed"); msg_Err(va, "IDirectXVideoDecoderService_GetDecoderConfigurations failed");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
msg_Dbg(va->log, "we got %d decoder configurations", cfg_count); msg_Dbg(va, "we got %d decoder configurations", cfg_count);
/* Select the best decoder configuration */ /* Select the best decoder configuration */
int cfg_score = 0; int cfg_score = 0;
...@@ -946,7 +940,7 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va, ...@@ -946,7 +940,7 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va,
const DXVA2_ConfigPictureDecode *cfg = &cfg_list[i]; const DXVA2_ConfigPictureDecode *cfg = &cfg_list[i];
/* */ /* */
msg_Dbg(va->log, "configuration[%d] ConfigBitstreamRaw %d", msg_Dbg(va, "configuration[%d] ConfigBitstreamRaw %d",
i, cfg->ConfigBitstreamRaw); i, cfg->ConfigBitstreamRaw);
/* */ /* */
...@@ -961,33 +955,34 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va, ...@@ -961,33 +955,34 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va,
score += 16; score += 16;
if (cfg_score < score) { if (cfg_score < score) {
va->cfg = *cfg; sys->cfg = *cfg;
cfg_score = score; cfg_score = score;
} }
} }
CoTaskMemFree(cfg_list); CoTaskMemFree(cfg_list);
if (cfg_score <= 0) { if (cfg_score <= 0) {
msg_Err(va->log, "Failed to find a supported decoder configuration"); msg_Err(va, "Failed to find a supported decoder configuration");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* Create the decoder */ /* Create the decoder */
IDirectXVideoDecoder *decoder; IDirectXVideoDecoder *decoder;
if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(va->vs, if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder(sys->vs,
&va->input, &sys->input,
&dsc, &dsc,
&va->cfg, &sys->cfg,
va->hw_surface, sys->hw_surface,
va->surface_count, sys->surface_count,
&decoder))) { &decoder))) {
msg_Err(va->log, "IDirectXVideoDecoderService_CreateVideoDecoder failed"); msg_Err(va, "IDirectXVideoDecoderService_CreateVideoDecoder failed");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
va->decoder = decoder; sys->decoder = decoder;
msg_Dbg(va->log, "IDirectXVideoDecoderService_CreateVideoDecoder succeed"); msg_Dbg(va, "IDirectXVideoDecoderService_CreateVideoDecoder succeed");
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static void DxDestroyVideoDecoder(vlc_va_dxva2_t *va)
static void DxDestroyVideoDecoder(vlc_va_sys_t *va)
{ {
if (va->decoder) if (va->decoder)
IDirectXVideoDecoder_Release(va->decoder); IDirectXVideoDecoder_Release(va->decoder);
...@@ -997,13 +992,14 @@ static void DxDestroyVideoDecoder(vlc_va_dxva2_t *va) ...@@ -997,13 +992,14 @@ static void DxDestroyVideoDecoder(vlc_va_dxva2_t *va)
IDirect3DSurface9_Release(va->surface[i].d3d); IDirect3DSurface9_Release(va->surface[i].d3d);
va->surface_count = 0; va->surface_count = 0;
} }
static int DxResetVideoDecoder(vlc_va_dxva2_t *va)
static int DxResetVideoDecoder(vlc_va_t *va)
{ {
msg_Err(va->log, "DxResetVideoDecoder unimplemented"); msg_Err(va, "DxResetVideoDecoder unimplemented");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
static void DxCreateVideoConversion(vlc_va_dxva2_t *va) static void DxCreateVideoConversion(vlc_va_sys_t *va)
{ {
switch (va->render) { switch (va->render) {
case MAKEFOURCC('N','V','1','2'): case MAKEFOURCC('N','V','1','2'):
...@@ -1016,7 +1012,8 @@ static void DxCreateVideoConversion(vlc_va_dxva2_t *va) ...@@ -1016,7 +1012,8 @@ static void DxCreateVideoConversion(vlc_va_dxva2_t *va)
} }
CopyInitCache(&va->surface_cache, va->surface_width); CopyInitCache(&va->surface_cache, va->surface_width);
} }
static void DxDestroyVideoConversion(vlc_va_dxva2_t *va)
static void DxDestroyVideoConversion(vlc_va_sys_t *va)
{ {
CopyCleanCache(&va->surface_cache); CopyCleanCache(&va->surface_cache);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment