Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 73 +++++++++++++++++++++-- dlls/evr/tests/Makefile.in | 2 +- dlls/evr/tests/evr.c | 116 ++++++++++++++++++++++++++++++++++++- 3 files changed, 185 insertions(+), 6 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 931554b5479..a65e82d4ca8 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -379,7 +379,7 @@ static HRESULT WINAPI video_mixer_transform_AddInputStreams(IMFTransform *iface, static HRESULT WINAPI video_mixer_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - FIXME("%p, %u, %u, %p.\n", iface, id, index, type); + TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
return E_NOTIMPL; } @@ -392,11 +392,76 @@ static HRESULT WINAPI video_mixer_transform_GetOutputAvailableType(IMFTransform return E_NOTIMPL; }
-static HRESULT WINAPI video_mixer_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +static HRESULT video_mixer_init_dxva_videodesc(IMFMediaType *media_type, DXVA2_VideoDesc *video_desc) { - FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags); + const MFVIDEOFORMAT *video_format; + IMFVideoMediaType *video_type; + BOOL is_compressed = TRUE; + HRESULT hr = S_OK;
- return E_NOTIMPL; + if (FAILED(IMFMediaType_QueryInterface(media_type, &IID_IMFVideoMediaType, (void **)&video_type))) + return MF_E_INVALIDMEDIATYPE; + + video_format = IMFVideoMediaType_GetVideoFormat(video_type); + IMFVideoMediaType_IsCompressedFormat(video_type, &is_compressed); + + if (!video_format || !video_format->videoInfo.dwWidth || !video_format->videoInfo.dwHeight || is_compressed) + { + hr = MF_E_INVALIDMEDIATYPE; + goto done; + } + + memset(video_desc, 0, sizeof(*video_desc)); + video_desc->SampleWidth = video_format->videoInfo.dwWidth; + video_desc->SampleWidth = video_format->videoInfo.dwHeight; + video_desc->Format = video_format->surfaceInfo.Format; + +done: + IMFVideoMediaType_Release(video_type); + + return hr; +} + +static HRESULT WINAPI video_mixer_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *media_type, DWORD flags) +{ + struct video_mixer *mixer = impl_from_IMFTransform(iface); + IDirectXVideoProcessorService *service; + DXVA2_VideoDesc video_desc; + HRESULT hr = E_NOTIMPL; + HANDLE handle; + + TRACE("%p, %u, %p, %#x.\n", iface, id, media_type, flags); + + if (id) + { + FIXME("Unimplemented for substreams.\n"); + return E_NOTIMPL; + } + + EnterCriticalSection(&mixer->cs); + + if (!mixer->device_manager) + hr = MF_E_NOT_INITIALIZED; + else + { + if (SUCCEEDED(hr = IDirect3DDeviceManager9_OpenDeviceHandle(mixer->device_manager, &handle))) + { + if (SUCCEEDED(hr = IDirect3DDeviceManager9_GetVideoService(mixer->device_manager, handle, + &IID_IDirectXVideoProcessorService, (void **)&service))) + { + if (SUCCEEDED(hr = video_mixer_init_dxva_videodesc(media_type, &video_desc))) + { + FIXME("Probe for supported devices.\n"); + hr = E_NOTIMPL; + } + } + IDirect3DDeviceManager9_CloseDeviceHandle(mixer->device_manager, handle); + } + } + + LeaveCriticalSection(&mixer->cs); + + return hr; }
static HRESULT WINAPI video_mixer_transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) diff --git a/dlls/evr/tests/Makefile.in b/dlls/evr/tests/Makefile.in index 8253c4d7fb4..5bd82277d1b 100644 --- a/dlls/evr/tests/Makefile.in +++ b/dlls/evr/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = evr.dll -IMPORTS = mfuuid strmiids uuid dxguid ole32 oleaut32 evr d3d9 user32 +IMPORTS = dxva2 mfplat mfuuid strmiids uuid dxguid ole32 oleaut32 evr d3d9 user32
C_SRCS = \ evr.c diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index 9365856d1eb..44819c1b387 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -19,16 +19,20 @@ */
#define COBJMACROS + #include "dshow.h" #include "wine/test.h" #include "d3d9.h" #include "evr.h" +#include "mferror.h" +#include "mfapi.h" #include "initguid.h" #include "dxva2api.h" -#include "mferror.h"
static const WCHAR sink_id[] = {'E','V','R',' ','I','n','p','u','t','0',0};
+static HRESULT (WINAPI *pMFCreateVideoMediaTypeFromSubtype)(const GUID *subtype, IMFVideoMediaType **video_type); + static HWND create_window(void) { RECT r = {0, 0, 640, 480}; @@ -626,16 +630,126 @@ done: DestroyWindow(window); }
+static void test_default_mixer_type_negotiation(void) +{ + IDirect3DDeviceManager9 *manager; + IMFVideoMediaType *video_type; + IMFMediaType *media_type; + IDirect3DDevice9 *device; + IMFTransform *transform; + IDirect3D9 *d3d; + HWND window; + HRESULT hr; + UINT token; + + if (!pMFCreateVideoMediaTypeFromSubtype) + { + win_skip("Skipping mixer types tests.\n"); + return; + } + + hr = MFCreateVideoMixer(NULL, &IID_IDirect3DDevice9, &IID_IMFTransform, (void **)&transform); + ok(hr == S_OK, "Failed to create default mixer, hr %#x.\n", hr); + + hr = IMFTransform_GetInputAvailableType(transform, 0, 0, &media_type); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); +todo_wine + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr); + + /* Now try with device manager. */ + + window = create_window(); + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + if (!(device = create_device(d3d, window))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + goto done; + } + + hr = DXVA2CreateDirect3DDeviceManager9(&token, &manager); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)manager); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + /* Now manager is not initialized. */ + hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + ok(hr == DXVA2_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr); + + hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + /* And now type description is incomplete. */ + hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + IMFMediaType_Release(media_type); + + hr = pMFCreateVideoMediaTypeFromSubtype(&MFVideoFormat_RGB32, &video_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + /* Partially initialized type. */ + hr = IMFTransform_SetInputType(transform, 0, (IMFMediaType *)video_type, 0); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + + /* Only required data - frame size and uncompressed marker. */ + hr = IMFVideoMediaType_SetUINT64(video_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFVideoMediaType_SetUINT32(video_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_SetInputType(transform, 0, (IMFMediaType *)video_type, 0); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + ok(media_type != (IMFMediaType *)video_type, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + } + + IMFVideoMediaType_Release(video_type); + + IDirect3DDeviceManager9_Release(manager); + + IDirect3DDevice9_Release(device); + +done: + IMFTransform_Release(transform); + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + START_TEST(evr) { CoInitialize(NULL);
+ pMFCreateVideoMediaTypeFromSubtype = (void *)GetProcAddress(GetModuleHandleA("mfplat.dll"), "MFCreateVideoMediaTypeFromSubtype"); + test_aggregation(); test_interfaces(); test_enum_pins(); test_find_pin(); test_pin_info(); test_default_mixer(); + test_default_mixer_type_negotiation(); test_surface_sample();
CoUninitialize();