Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index eaea037b693..931554b5479 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -21,6 +21,7 @@ #include "wine/debug.h" #include "evr.h" #include "d3d9.h" +#include "dxva2api.h" #include "mfapi.h" #include "mferror.h"
@@ -47,6 +48,9 @@ struct video_mixer struct input_stream inputs[MAX_MIXER_INPUT_STREAMS]; unsigned int input_ids[MAX_MIXER_INPUT_STREAMS]; unsigned int input_count; + + IDirect3DDeviceManager9 *device_manager; + CRITICAL_SECTION cs; };
@@ -151,6 +155,8 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface) if (mixer->inputs[i].attributes) IMFAttributes_Release(mixer->inputs[i].attributes); } + if (mixer->device_manager) + IDirect3DDeviceManager9_Release(mixer->device_manager); DeleteCriticalSection(&mixer->cs); free(mixer); } @@ -444,9 +450,32 @@ static HRESULT WINAPI video_mixer_transform_ProcessEvent(IMFTransform *iface, DW
static HRESULT WINAPI video_mixer_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) { - FIXME("%p, %u, %#lx.\n", iface, message, param); + struct video_mixer *mixer = impl_from_IMFTransform(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %#lx.\n", iface, message, param); + + switch (message) + { + case MFT_MESSAGE_SET_D3D_MANAGER: + + EnterCriticalSection(&mixer->cs); + + if (mixer->device_manager) + IDirect3DDeviceManager9_Release(mixer->device_manager); + mixer->device_manager = NULL; + if (param) + hr = IUnknown_QueryInterface((IUnknown *)param, &IID_IDirect3DDeviceManager9, (void **)&mixer->device_manager); + + LeaveCriticalSection(&mixer->cs); + + break; + default: + WARN("Message not handled %d.\n", message); + hr = E_NOTIMPL; + } + + return hr; }
static HRESULT WINAPI video_mixer_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
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();
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- include/dxva2api.idl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/include/dxva2api.idl b/include/dxva2api.idl index eb4a26509a1..f8c8e476d26 100644 --- a/include/dxva2api.idl +++ b/include/dxva2api.idl @@ -805,23 +805,24 @@ cpp_quote("#endif")
cpp_quote("static inline DXVA2_Fixed32 DXVA2_Fixed32OpaqueAlpha(void) {") cpp_quote(" DXVA2_Fixed32 f32;") -cpp_quote(" f32.ll = 0 + (1 << 16);") +cpp_quote(" *(LONG *)&f32 = 0 + (1 << 16);") cpp_quote(" return f32;") cpp_quote("}") cpp_quote("") cpp_quote("static inline DXVA2_Fixed32 DXVA2_Fixed32TransparentAlpha(void) {") -cpp_quote(" DXVA2_Fixed32 f32;") -cpp_quote(" f32.ll = 0;") +cpp_quote(" DXVA2_Fixed32 f32 = { 0 };") cpp_quote(" return f32;") cpp_quote("}") cpp_quote("") cpp_quote("static inline float DXVA2FixedToFloat(DXVA2_Fixed32 f32) {") -cpp_quote(" return (float)f32.Value + (float)f32.Fraction / (1 << 16);") +cpp_quote(" struct { USHORT Fraction; SHORT Value; } *_f32 = (void *)&f32;") +cpp_quote(" return (float)_f32->Value + (float)_f32->Fraction / (1 << 16);") cpp_quote("}") cpp_quote("") cpp_quote("static inline DXVA2_Fixed32 DXVA2FloatToFixed(float f) {") cpp_quote(" DXVA2_Fixed32 f32;") -cpp_quote(" f32.Value = ((ULONG) (f * (1 << 16))) >> 16;") -cpp_quote(" f32.Fraction = ((ULONG) (f * (1 << 16))) & 0xFFFF;") +cpp_quote(" struct { USHORT Fraction; SHORT Value; } *_f32 = (void *)&f32;") +cpp_quote(" _f32->Value = ((ULONG) (f * (1 << 16))) >> 16;") +cpp_quote(" _f32->Fraction = ((ULONG) (f * (1 << 16))) & 0xFFFF;") cpp_quote(" return f32;") cpp_quote("}")
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/mediatype.c | 34 ++++++++++++++++++++++++++++++++++ dlls/mfplat/mfplat.spec | 2 +- include/mfapi.h | 1 + 3 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 843c09c5e09..5eaa4fdd08d 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -23,6 +23,7 @@ #include "initguid.h" #include "ks.h" #include "ksmedia.h" +#include "dxva2api.h"
#include "wine/debug.h"
@@ -2748,3 +2749,36 @@ HRESULT WINAPI MFCreateMFVideoFormatFromMFMediaType(IMFMediaType *media_type, MF
return S_OK; } + +/*********************************************************************** + * MFConvertColorInfoToDXVA (mfplat.@) + */ +HRESULT WINAPI MFConvertColorInfoToDXVA(DWORD *dxva_info, const MFVIDEOFORMAT *format) +{ + struct + { + UINT SampleFormat : 8; + UINT VideoChromaSubsampling : 4; + UINT NominalRange : 3; + UINT VideoTransferMatrix : 3; + UINT VideoLighting : 4; + UINT VideoPrimaries : 5; + UINT VideoTransferFunction : 5; + } *dxva_format = (void *)dxva_info; + + TRACE("%p, %p.\n", dxva_info, format); + + if (format->videoInfo.InterlaceMode == MFVideoInterlace_MixedInterlaceOrProgressive) + dxva_format->SampleFormat = DXVA2_SampleFieldInterleavedEvenFirst; + else + dxva_format->SampleFormat = format->videoInfo.InterlaceMode; + + dxva_format->VideoChromaSubsampling = format->videoInfo.SourceChromaSubsampling; + dxva_format->NominalRange = format->videoInfo.NominalRange; + dxva_format->VideoTransferMatrix = format->videoInfo.TransferMatrix; + dxva_format->VideoLighting = format->videoInfo.SourceLighting; + dxva_format->VideoPrimaries = format->videoInfo.ColorPrimaries; + dxva_format->VideoTransferFunction = format->videoInfo.TransferFunction; + + return S_OK; +} diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index e6069424fc9..16be972e5bd 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -34,7 +34,7 @@ @ stdcall MFCompareFullToPartialMediaType(ptr ptr) @ stub MFCompareSockaddrAddresses @ stub MFConvertColorInfoFromDXVA -@ stub MFConvertColorInfoToDXVA +@ stdcall MFConvertColorInfoToDXVA(ptr ptr) @ stub MFConvertFromFP16Array @ stub MFConvertToFP16Array @ stdcall MFCopyImage(ptr long ptr long long long) diff --git a/include/mfapi.h b/include/mfapi.h index e86fb526f13..06a5412cbc5 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -494,6 +494,7 @@ HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie); HRESULT WINAPI MFCancelWorkItem(MFWORKITEM_KEY key); BOOL WINAPI MFCompareFullToPartialMediaType(IMFMediaType *full_type, IMFMediaType *partial_type); +HRESULT WINAPI MFConvertColorInfoToDXVA(DWORD *dxva_info, const MFVIDEOFORMAT *format); HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines); HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer); HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer);