Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/evr/mixer.c | 201 +++++++++++++++++++++++++++++++++++++++---- dlls/evr/tests/evr.c | 87 ++++++++++++++++++- 2 files changed, 269 insertions(+), 19 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index e8905f633ab..6fcad15ec64 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -18,7 +18,6 @@
#define COBJMACROS
-#include "wine/debug.h" #include "evr.h" #include "d3d9.h" #include "dxva2api.h" @@ -30,6 +29,9 @@ #include "initguid.h" #include "evr9.h"
+#include "wine/debug.h" +#include "wine/heap.h" + WINE_DEFAULT_DEBUG_CHANNEL(evr);
#define MAX_MIXER_INPUT_STREAMS 16 @@ -38,6 +40,14 @@ struct input_stream { unsigned int id; IMFAttributes *attributes; + IMFVideoMediaType *media_type; +}; + +struct output_stream +{ + IMFVideoMediaType *media_type; + IMFVideoMediaType **media_types; + unsigned int type_count; };
struct video_mixer @@ -55,6 +65,7 @@ struct video_mixer struct input_stream inputs[MAX_MIXER_INPUT_STREAMS]; unsigned int input_ids[MAX_MIXER_INPUT_STREAMS]; unsigned int input_count; + struct output_stream output;
IDirect3DDeviceManager9 *device_manager;
@@ -122,6 +133,26 @@ static void video_mixer_init_input(struct input_stream *stream) IMFAttributes_SetUINT32(stream->attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, 1); }
+static void video_mixer_clear_types(struct video_mixer *mixer) +{ + unsigned int i; + + for (i = 0; i < mixer->input_count; ++i) + { + if (mixer->inputs[i].media_type) + IMFVideoMediaType_Release(mixer->inputs[i].media_type); + mixer->inputs[i].media_type = NULL; + } + for (i = 0; i < mixer->output.type_count; ++i) + { + IMFVideoMediaType_Release(mixer->output.media_types[i]); + } + heap_free(mixer->output.media_types); + if (mixer->output.media_type) + IMFVideoMediaType_Release(mixer->output.media_type); + mixer->output.media_type = NULL; +} + static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) { struct video_mixer *mixer = impl_from_IMFTransform(iface); @@ -198,6 +229,7 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface) if (mixer->inputs[i].attributes) IMFAttributes_Release(mixer->inputs[i].attributes); } + video_mixer_clear_types(mixer); if (mixer->device_manager) IDirect3DDeviceManager9_Release(mixer->device_manager); DeleteCriticalSection(&mixer->cs); @@ -430,9 +462,27 @@ static HRESULT WINAPI video_mixer_transform_GetInputAvailableType(IMFTransform * static HRESULT WINAPI video_mixer_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, IMFMediaType **type) { - FIXME("%p, %u, %u, %p.\n", iface, id, index, type); + struct video_mixer *mixer = impl_from_IMFTransform(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %u, %p.\n", iface, id, index, type); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&mixer->cs); + + if (index >= mixer->output.type_count) + hr = MF_E_NO_MORE_TYPES; + else + { + *type = (IMFMediaType *)mixer->output.media_types[index]; + IMFMediaType_AddRef(*type); + } + + LeaveCriticalSection(&mixer->cs); + + return hr; }
static HRESULT video_mixer_init_dxva_videodesc(IMFMediaType *media_type, DXVA2_VideoDesc *video_desc) @@ -465,24 +515,93 @@ done: return hr; }
+static int rt_formats_sort_compare(const void *left, const void *right) +{ + D3DFORMAT format1 = *(D3DFORMAT *)left, format2 = *(D3DFORMAT *)right; + + if (format1 < format2) return -1; + if (format1 > format2) return 1; + return 0; +} + +static HRESULT video_mixer_collect_output_types(struct video_mixer *mixer, const DXVA2_VideoDesc *video_desc, + IDirectXVideoProcessorService *service, unsigned int device_count, const GUID *devices) +{ + unsigned int i, j, format_count, count; + D3DFORMAT *rt_formats = NULL, *formats, *ptr; + GUID subtype; + HRESULT hr; + + count = 0; + for (i = 0; i < device_count; ++i) + { + if (SUCCEEDED(IDirectXVideoProcessorService_GetVideoProcessorRenderTargets(service, &devices[i], video_desc, + &format_count, &formats))) + { + if (!(ptr = heap_realloc(rt_formats, (count + format_count) * sizeof(*rt_formats)))) + { + hr = E_OUTOFMEMORY; + CoTaskMemFree(formats); + break; + } + rt_formats = ptr; + + memcpy(&rt_formats[count], formats, format_count * sizeof(*formats)); + count += format_count; + + CoTaskMemFree(formats); + } + } + + if (count) + { + qsort(rt_formats, count, sizeof(*rt_formats), rt_formats_sort_compare); + + j = 0; + for (i = j + 1; i < count; ++i) + { + if (rt_formats[i] != rt_formats[j]) + { + rt_formats[++j] = rt_formats[i]; + } + } + count = j + 1; + + memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype)); + if ((mixer->output.media_types = heap_calloc(count, sizeof(*mixer->output.media_types)))) + { + for (i = 0; i < count; ++i) + { + subtype.Data1 = rt_formats[i]; + MFCreateVideoMediaTypeFromSubtype(&subtype, &mixer->output.media_types[i]); + } + mixer->output.type_count = count; + } + else + hr = E_OUTOFMEMORY; + } + + heap_free(rt_formats); + + 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; + unsigned int count; HANDLE handle; + GUID *guids;
TRACE("%p, %u, %p, %#x.\n", iface, id, media_type, flags);
- if (id) - { - FIXME("Unimplemented for substreams.\n"); - return E_NOTIMPL; - } - EnterCriticalSection(&mixer->cs);
+ video_mixer_clear_types(mixer); + if (!mixer->device_manager) hr = MF_E_NOT_INITIALIZED; else @@ -494,8 +613,21 @@ static HRESULT WINAPI video_mixer_transform_SetInputType(IMFTransform *iface, DW { if (SUCCEEDED(hr = video_mixer_init_dxva_videodesc(media_type, &video_desc))) { - FIXME("Probe for supported devices.\n"); - hr = E_NOTIMPL; + if (!id) + { + if (SUCCEEDED(hr = IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids(service, &video_desc, + &count, &guids))) + { + if (SUCCEEDED(hr = video_mixer_collect_output_types(mixer, &video_desc, service, count, guids))) + FIXME("Set input type.\n"); + CoTaskMemFree(guids); + } + } + else + { + FIXME("Unimplemented for substreams.\n"); + hr = E_NOTIMPL; + } } } IDirect3DDeviceManager9_CloseDeviceHandle(mixer->device_manager, handle); @@ -516,16 +648,55 @@ static HRESULT WINAPI video_mixer_transform_SetOutputType(IMFTransform *iface, D
static HRESULT WINAPI video_mixer_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) { - FIXME("%p, %u, %p.\n", iface, id, type); + struct video_mixer *mixer = impl_from_IMFTransform(iface); + struct input_stream *stream; + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, id, type); + + EnterCriticalSection(&mixer->cs); + + if ((stream = video_mixer_get_input(mixer, id))) + { + if (!stream->media_type) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else + { + *type = (IMFMediaType *)stream->media_type; + IMFMediaType_AddRef(*type); + } + } + else + hr = MF_E_INVALIDSTREAMNUMBER; + + LeaveCriticalSection(&mixer->cs); + + return hr; }
static HRESULT WINAPI video_mixer_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) { - FIXME("%p, %u, %p.\n", iface, id, type); + struct video_mixer *mixer = impl_from_IMFTransform(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, id, type); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&mixer->cs); + + if (!mixer->output.media_type) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else + { + *type = (IMFMediaType *)mixer->output.media_type; + IMFMediaType_AddRef(*type); + } + + LeaveCriticalSection(&mixer->cs); + + return hr; }
static HRESULT WINAPI video_mixer_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index c37f921b09e..6259e636328 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -376,17 +376,23 @@ static void test_pin_info(void) static void test_default_mixer(void) { DWORD input_min, input_max, output_min, output_max; + IMFAttributes *attributes, *attributes2; MFT_OUTPUT_STREAM_INFO output_info; MFT_INPUT_STREAM_INFO input_info; DWORD input_count, output_count; + IMFVideoProcessor *processor; IMFVideoDeviceID *deviceid; DWORD input_id, output_id; - IMFAttributes *attributes, *attributes2; IMFTransform *transform; + DXVA2_ValueRange range; + DXVA2_Fixed32 value; IMFGetService *gs; + COLORREF color; unsigned int i; DWORD ids[16]; IUnknown *unk; + DWORD count; + GUID *guids; HRESULT hr; IID iid;
@@ -404,9 +410,37 @@ static void test_default_mixer(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); IUnknown_Release(unk);
- hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, (void **)&unk); + hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, (void **)&processor); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - IUnknown_Release(unk); + + color = 1; + hr = IMFVideoProcessor_GetBackgroundColor(processor, &color); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!color, "Unexpected color %#x.\n", color); +} + hr = IMFVideoProcessor_SetBackgroundColor(processor, 0x00121212); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoProcessor_GetBackgroundColor(processor, &color); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(color == 0x121212, "Unexpected color %#x.\n", color); +} + hr = IMFVideoProcessor_GetFilteringRange(processor, DXVA2_DetailFilterChromaLevel, &range); +todo_wine + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoProcessor_GetFilteringValue(processor, DXVA2_DetailFilterChromaLevel, &value); +todo_wine + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoProcessor_GetAvailableVideoProcessorModes(processor, &count, &guids); +todo_wine + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + IMFVideoProcessor_Release(processor);
hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoPositionMapper, (void **)&unk); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); @@ -663,12 +697,17 @@ done: static void test_default_mixer_type_negotiation(void) { IDirect3DDeviceManager9 *manager; + DXVA2_VideoProcessorCaps caps; IMFVideoMediaType *video_type; + IMFVideoProcessor *processor; IMFMediaType *media_type; IDirect3DDevice9 *device; IMFTransform *transform; + GUID guid, *guids; IDirect3D9 *d3d; + IUnknown *unk; HWND window; + DWORD count; HRESULT hr; UINT token;
@@ -685,7 +724,6 @@ static void test_default_mixer_type_negotiation(void) 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); @@ -746,15 +784,56 @@ todo_wine todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoProcessor, (void **)&processor); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoProcessor_GetVideoProcessorMode(processor, &guid); +todo_wine + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoProcessor_GetVideoProcessorCaps(processor, (GUID *)&DXVA2_VideoProcSoftwareDevice, &caps); +todo_wine + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "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"); + hr = IMFMediaType_QueryInterface(media_type, &IID_IMFVideoMediaType, (void **)&unk); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IUnknown_Release(unk); + IMFMediaType_Release(media_type); + } + + hr = IMFVideoProcessor_GetAvailableVideoProcessorModes(processor, &count, &guids); +todo_wine + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + if (SUCCEEDED(hr)) + { + hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); IMFMediaType_Release(media_type); }
+ hr = IMFVideoProcessor_GetVideoProcessorMode(processor, &guid); +todo_wine + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoProcessor_GetAvailableVideoProcessorModes(processor, &count, &guids); +todo_wine + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + CoTaskMemFree(guids); + + IMFVideoProcessor_Release(processor); + IMFVideoMediaType_Release(video_type);
IDirect3DDeviceManager9_Release(manager);