evr: Add input type validation through dxva.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
881336569c
commit
43eebcd3e6
201
dlls/evr/mixer.c
201
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue