Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- include/mfidl.idl | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/include/mfidl.idl b/include/mfidl.idl index 82f69518df..fc9173864a 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -925,13 +925,20 @@ interface IMFMediaSourceTopologyProvider : IUnknown HRESULT GetMediaSourceTopology([in] IMFPresentationDescriptor *pd, [out] IMFTopology **topology); }
-cpp_quote("#define MF_RESOLUTION_MEDIASOURCE 0x00000001") -cpp_quote("#define MF_RESOLUTION_BYTESTREAM 0x00000002") -cpp_quote("#define MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE 0x00000010") -cpp_quote("#define MF_RESOLUTION_KEEP_BYTE_STREAM_ALIVE_ON_FAIL 0x00000020") -cpp_quote("#define MF_RESOLUTION_READ 0x00010000") -cpp_quote("#define MF_RESOLUTION_WRITE 0x00020000") -cpp_quote("#define MF_RESOLUTION_DISABLE_LOCAL_PLUGINS 0x00000040") +enum +{ + MF_RESOLUTION_MEDIASOURCE = 0x00000001, + MF_RESOLUTION_BYTESTREAM = 0x00000002, + MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE = 0x00000010, + MF_RESOLUTION_KEEP_BYTE_STREAM_ALIVE_ON_FAIL = 0x00000020, + MF_RESOLUTION_DISABLE_LOCAL_PLUGINS = 0x00000040, + MF_RESOLUTION_PLUGIN_CONTROL_POLICY_APPROVED_ONLY = 0x00000080, + MF_RESOLUTION_PLUGIN_CONTROL_POLICY_WEB_ONLY = 0x00000100, + MF_RESOLUTION_PLUGIN_CONTROL_POLICY_WEB_ONLY_EDGEMODE = 0x00000200, + MF_RESOLUTION_ENABLE_STORE_PLUGINS = 0x00000400, + MF_RESOLUTION_READ = 0x00010000, + MF_RESOLUTION_WRITE = 0x00020000, +};
cpp_quote("#ifdef __cplusplus") cpp_quote("static inline HRESULT MFSetAttributeSize(IMFAttributes *attributes, REFGUID key, UINT32 width, UINT32 height)")
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/main.c | 544 +++++++++++++++++++++++++++++++++++++++++++++ dlls/mf/mf.spec | 2 +- dlls/mf/tests/mf.c | 271 ++++++++++++++++++++++ include/mfidl.idl | 1 + 4 files changed, 817 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/main.c b/dlls/mf/main.c index 1700b179e5..f38558f82e 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -1461,3 +1461,547 @@ HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler)
return S_OK; } + +enum sample_copier_flags +{ + SAMPLE_COPIER_INPUT_TYPE_SET = 0x1, + SAMPLE_COPIER_OUTPUT_TYPE_SET = 0x2 +}; + +struct sample_copier +{ + IMFTransform IMFTransform_iface; + LONG refcount; + + IMFAttributes *attributes; + IMFMediaType *buffer_type; + DWORD buffer_size; + IMFSample *sample; + DWORD flags; + CRITICAL_SECTION cs; +}; + +static struct sample_copier *impl_copier_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct sample_copier, IMFTransform_iface); +} + +static HRESULT WINAPI sample_copier_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFTransform) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFTransform_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI sample_copier_transform_AddRef(IMFTransform *iface) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + ULONG refcount = InterlockedIncrement(&transform->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI sample_copier_transform_Release(IMFTransform *iface) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + ULONG refcount = InterlockedDecrement(&transform->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + IMFAttributes_Release(transform->attributes); + if (transform->buffer_type) + IMFMediaType_Release(transform->buffer_type); + DeleteCriticalSection(&transform->cs); + heap_free(transform); + } + + return refcount; +} + +static HRESULT WINAPI sample_copier_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum); + + *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + TRACE("%p, %p, %p.\n", iface, inputs, outputs); + + *inputs = 1; + *outputs = 1; + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, + DWORD output_size, DWORD *outputs) +{ + TRACE("%p, %u, %p, %u, %p.\n", iface, input_size, inputs, output_size, outputs); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, info); + + memset(info, 0, sizeof(*info)); + + EnterCriticalSection(&transform->cs); + info->cbSize = transform->buffer_size; + LeaveCriticalSection(&transform->cs); + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, + MFT_OUTPUT_STREAM_INFO *info) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, info); + + memset(info, 0, sizeof(*info)); + + EnterCriticalSection(&transform->cs); + info->cbSize = transform->buffer_size; + LeaveCriticalSection(&transform->cs); + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + + TRACE("%p, %p.\n", iface, attributes); + + *attributes = transform->attributes; + IMFAttributes_AddRef(*attributes); + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, + IMFAttributes **attributes) +{ + TRACE("%p, %u, %p.\n", iface, id, attributes); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, + IMFAttributes **attributes) +{ + TRACE("%p, %u, %p.\n", iface, id, attributes); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + TRACE("%p, %u.\n", iface, id); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + TRACE("%p, %u, %p.\n", iface, streams, ids); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + static const GUID *types[] = { &MFMediaType_Video, &MFMediaType_Audio }; + HRESULT hr; + + TRACE("%p, %u, %u, %p.\n", iface, id, index, type); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + if (index > ARRAY_SIZE(types) - 1) + return MF_E_NO_MORE_TYPES; + + if (SUCCEEDED(hr = MFCreateMediaType(type))) + hr = IMFMediaType_SetGUID(*type, &MF_MT_MAJOR_TYPE, types[index]); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + IMFMediaType *cloned_type = NULL; + HRESULT hr = S_OK; + + TRACE("%p, %u, %u, %p.\n", iface, id, index, type); + + EnterCriticalSection(&transform->cs); + if (transform->buffer_type) + { + if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type))) + hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type); + } + else if (id) + hr = MF_E_INVALIDSTREAMNUMBER; + else + hr = MF_E_NO_MORE_TYPES; + LeaveCriticalSection(&transform->cs); + + if (SUCCEEDED(hr)) + *type = cloned_type; + else if (cloned_type) + IMFMediaType_Release(cloned_type); + + return hr; +} + +static HRESULT sample_copier_get_buffer_size(IMFMediaType *type, DWORD *size) +{ + GUID major, subtype; + UINT64 frame_size; + HRESULT hr; + + *size = 0; + + if (FAILED(hr = IMFMediaType_GetMajorType(type, &major))) + return hr; + + if (IsEqualGUID(&major, &MFMediaType_Video)) + { + if (SUCCEEDED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) + { + if (SUCCEEDED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) + { + if (FAILED(hr = MFCalculateImageSize(&subtype, (UINT32)(frame_size >> 32), (UINT32)frame_size, size))) + WARN("Failed to get image size for video format %s.\n", debugstr_guid(&subtype)); + } + } + } + else if (IsEqualGUID(&major, &MFMediaType_Audio)) + { + FIXME("Audio formats are not handled.\n"); + hr = E_NOTIMPL; + } + + return hr; +} + +static HRESULT sample_copier_set_media_type(struct sample_copier *transform, BOOL input, DWORD id, IMFMediaType *type, + DWORD flags) +{ + DWORD buffer_size; + HRESULT hr = S_OK; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&transform->cs); + if (type) + { + hr = sample_copier_get_buffer_size(type, &buffer_size); + if (!(flags & MFT_SET_TYPE_TEST_ONLY) && SUCCEEDED(hr)) + { + if (!transform->buffer_type) + hr = MFCreateMediaType(&transform->buffer_type); + if (SUCCEEDED(hr)) + hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)transform->buffer_type); + if (SUCCEEDED(hr)) + transform->buffer_size = buffer_size; + + if (SUCCEEDED(hr)) + { + if (input) + { + transform->flags |= SAMPLE_COPIER_INPUT_TYPE_SET; + transform->flags &= ~SAMPLE_COPIER_OUTPUT_TYPE_SET; + } + else + transform->flags |= SAMPLE_COPIER_OUTPUT_TYPE_SET; + } + } + } + else if (transform->buffer_type) + { + IMFMediaType_Release(transform->buffer_type); + transform->buffer_type = NULL; + } + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + + TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags); + + return sample_copier_set_media_type(transform, TRUE, id, type, flags); +} + +static HRESULT WINAPI sample_copier_transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + + TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags); + + return sample_copier_set_media_type(transform, FALSE, id, type, flags); +} + +static HRESULT sample_copier_get_current_type(struct sample_copier *transform, DWORD id, DWORD flags, + IMFMediaType **ret) +{ + IMFMediaType *cloned_type = NULL; + HRESULT hr; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&transform->cs); + if (transform->flags & flags) + { + if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type))) + hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type); + } + else + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + LeaveCriticalSection(&transform->cs); + + if (SUCCEEDED(hr)) + *ret = cloned_type; + else if (cloned_type) + IMFMediaType_Release(cloned_type); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, type); + + return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_INPUT_TYPE_SET, type); +} + +static HRESULT WINAPI sample_copier_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, type); + + return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_OUTPUT_TYPE_SET, type); +} + +static HRESULT WINAPI sample_copier_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + HRESULT hr = S_OK; + + TRACE("%p, %u, %p.\n", iface, id, flags); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&transform->cs); + if (!(transform->flags & SAMPLE_COPIER_INPUT_TYPE_SET)) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else + *flags = transform->sample ? 0 : MFT_INPUT_STATUS_ACCEPT_DATA; + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_GetOutputStatus(IMFTransform *iface, DWORD *flags) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + HRESULT hr = S_OK; + + TRACE("%p, %p.\n", iface, flags); + + EnterCriticalSection(&transform->cs); + if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET)) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else + *flags = transform->sample ? MFT_OUTPUT_STATUS_SAMPLE_READY : 0; + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) +{ + TRACE("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) +{ + FIXME("%p, %u, %p.\n", iface, id, event); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + + TRACE("%p, %#x, %p.\n", iface, message, (void *)param); + + EnterCriticalSection(&transform->cs); + + if (message == MFT_MESSAGE_COMMAND_FLUSH) + { + if (transform->sample) + { + IMFSample_Release(transform->sample); + transform->sample = NULL; + } + } + + LeaveCriticalSection(&transform->cs); + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + HRESULT hr = S_OK; + + TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&transform->cs); + if (!transform->buffer_type) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else if (transform->sample) + hr = MF_E_NOTACCEPTING; + else + { + transform->sample = sample; + IMFSample_AddRef(transform->sample); + } + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, + MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status) +{ + struct sample_copier *transform = impl_copier_from_IMFTransform(iface); + DWORD sample_flags; + HRESULT hr = S_OK; + LONGLONG time; + + TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, buffers, status); + + EnterCriticalSection(&transform->cs); + if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET)) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else if (!transform->sample) + hr = MF_E_TRANSFORM_NEED_MORE_INPUT; + else + { + IMFSample_CopyAllItems(transform->sample, (IMFAttributes *)buffers->pSample); + + if (SUCCEEDED(IMFSample_GetSampleDuration(transform->sample, &time))) + IMFSample_SetSampleDuration(buffers->pSample, time); + + if (SUCCEEDED(IMFSample_GetSampleTime(transform->sample, &time))) + IMFSample_SetSampleTime(buffers->pSample, time); + + if (SUCCEEDED(IMFSample_GetSampleFlags(transform->sample, &sample_flags))) + IMFSample_SetSampleFlags(buffers->pSample, sample_flags); + + FIXME("Copy buffers.\n"); + + IMFSample_Release(transform->sample); + transform->sample = NULL; + } + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static const IMFTransformVtbl sample_copier_transform_vtbl = +{ + sample_copier_transform_QueryInterface, + sample_copier_transform_AddRef, + sample_copier_transform_Release, + sample_copier_transform_GetStreamLimits, + sample_copier_transform_GetStreamCount, + sample_copier_transform_GetStreamIDs, + sample_copier_transform_GetInputStreamInfo, + sample_copier_transform_GetOutputStreamInfo, + sample_copier_transform_GetAttributes, + sample_copier_transform_GetInputStreamAttributes, + sample_copier_transform_GetOutputStreamAttributes, + sample_copier_transform_DeleteInputStream, + sample_copier_transform_AddInputStreams, + sample_copier_transform_GetInputAvailableType, + sample_copier_transform_GetOutputAvailableType, + sample_copier_transform_SetInputType, + sample_copier_transform_SetOutputType, + sample_copier_transform_GetInputCurrentType, + sample_copier_transform_GetOutputCurrentType, + sample_copier_transform_GetInputStatus, + sample_copier_transform_GetOutputStatus, + sample_copier_transform_SetOutputBounds, + sample_copier_transform_ProcessEvent, + sample_copier_transform_ProcessMessage, + sample_copier_transform_ProcessInput, + sample_copier_transform_ProcessOutput, +}; + +HRESULT WINAPI MFCreateSampleCopierMFT(IMFTransform **transform) +{ + struct sample_copier *object; + + TRACE("%p.\n", transform); + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IMFTransform_iface.lpVtbl = &sample_copier_transform_vtbl; + object->refcount = 1; + MFCreateAttributes(&object->attributes, 0); + InitializeCriticalSection(&object->cs); + + *transform = &object->IMFTransform_iface; + + return S_OK; +} diff --git a/dlls/mf/mf.spec b/dlls/mf/mf.spec index 29676005ad..1c3fc9c953 100644 --- a/dlls/mf/mf.spec +++ b/dlls/mf/mf.spec @@ -50,7 +50,7 @@ @ stub MFCreateProxyLocator @ stub MFCreateRemoteDesktopPlugin @ stub MFCreateSAMIByteStreamPlugin -@ stub MFCreateSampleCopierMFT +@ stdcall MFCreateSampleCopierMFT(ptr) @ stdcall MFCreateSampleGrabberSinkActivate(ptr ptr ptr) @ stub MFCreateSecureHttpSchemePlugin @ stub MFCreateSequencerSegmentOffset diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index cf98f3d03f..2dc5ad8f50 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2751,6 +2751,276 @@ static void test_MFGetSupportedSchemes(void) PropVariantClear(&value); }
+static BOOL is_sample_copier_available_type(IMFMediaType *type) +{ + GUID major = { 0 }; + UINT32 count; + HRESULT hr; + + hr = IMFMediaType_GetMajorType(type, &major); + ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr); + + hr = IMFMediaType_GetCount(type, &count); + ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); + ok(count == 1, "Unexpected attribute count %u.\n", count); + + return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio); +} + +static void test_sample_copier(void) +{ + DWORD in_min, in_max, out_min, out_max; + IMFMediaType *mediatype, *mediatype2; + MFT_OUTPUT_STREAM_INFO output_info; + IMFSample *sample, *client_sample; + MFT_INPUT_STREAM_INFO input_info; + DWORD input_count, output_count; + MFT_OUTPUT_DATA_BUFFER buffer; + IMFMediaBuffer *media_buffer; + IMFAttributes *attributes; + IMFTransform *copier; + DWORD flags, status; + HRESULT hr; + + hr = MFCreateSampleCopierMFT(&copier); + ok(hr == S_OK, "Failed to create sample copier, hr %#x.\n", hr); + + hr = IMFTransform_GetAttributes(copier, &attributes); + ok(hr == S_OK, "Failed to get transform attributes, hr %#x.\n", hr); + IMFAttributes_Release(attributes); + + hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_SetOutputBounds(copier, 0, 0); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + /* No dynamic streams. */ + input_count = output_count = 0; + hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count); + ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr); + ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n"); + + hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max); + ok(hr == S_OK, "Failed to get stream limits, hr %#x.\n", hr); + ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n"); + + hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_DeleteInputStream(copier, 0); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + /* Available types. */ + hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n"); + IMFMediaType_Release(mediatype); + + hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n"); + IMFMediaType_Release(mediatype); + + hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype); + ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype); + ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = MFCreateSample(&sample); + ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr); + + hr = IMFTransform_ProcessInput(copier, 0, sample, 0); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info); + ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr); + ok(!output_info.dwFlags, "Unexpected flags %#x.\n", output_info.dwFlags); + ok(!output_info.cbSize, "Unexpected size %u.\n", output_info.cbSize); + ok(!output_info.cbAlignment, "Unexpected alignment %u.\n", output_info.cbAlignment); + + hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info); + ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr); + + ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency)); + ok(!input_info.dwFlags, "Unexpected flags %#x.\n", input_info.dwFlags); + ok(!input_info.cbSize, "Unexpected size %u.\n", input_info.cbSize); + ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %u.\n", input_info.cbMaxLookahead); + ok(!input_info.cbAlignment, "Unexpected alignment %u.\n", input_info.cbAlignment); + + hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0); + ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info); + ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr); + ok(!output_info.dwFlags, "Unexpected flags %#x.\n", output_info.dwFlags); + ok(output_info.cbSize == 16 * 16, "Unexpected size %u.\n", output_info.cbSize); + ok(!output_info.cbAlignment, "Unexpected alignment %u.\n", output_info.cbAlignment); + + hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2); + ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr); + IMFMediaType_Release(mediatype2); + + hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetInputStatus(copier, 0, &flags); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + /* Setting input type resets output type. */ + hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IMFMediaType_Release(mediatype2); + + hr = IMFTransform_SetInputType(copier, 0, mediatype, 0); + ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr); + + hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n"); + IMFMediaType_Release(mediatype2); + + hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info); + ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr); + ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency)); + ok(!input_info.dwFlags, "Unexpected flags %#x.\n", input_info.dwFlags); + ok(input_info.cbSize == 16 * 16, "Unexpected size %u.\n", input_info.cbSize); + ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %u.\n", input_info.cbMaxLookahead); + ok(!input_info.cbAlignment, "Unexpected alignment %u.\n", input_info.cbAlignment); + + hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IMFMediaType_Release(mediatype2); + + hr = IMFTransform_GetInputStatus(copier, 0, &flags); + ok(hr == S_OK, "Failed to get input status, hr %#x.\n", hr); + ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#x.\n", flags); + + hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2); + ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr); + IMFMediaType_Release(mediatype2); + + hr = IMFTransform_GetOutputStatus(copier, &flags); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0); + ok(hr == S_OK, "Failed to set output type, hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStatus(copier, &flags); + ok(hr == S_OK, "Failed to get output status, hr %#x.\n", hr); + ok(!flags, "Unexpected flags %#x.\n", flags); + + /* Pushing samples. */ + hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer); + ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr); + + hr = IMFSample_AddBuffer(sample, media_buffer); + ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr); + IMFMediaBuffer_Release(media_buffer); + + EXPECT_REF(sample, 1); + hr = IMFTransform_ProcessInput(copier, 0, sample, 0); + ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr); + EXPECT_REF(sample, 2); + + hr = IMFTransform_GetInputStatus(copier, 0, &flags); + ok(hr == S_OK, "Failed to get input status, hr %#x.\n", hr); + ok(!flags, "Unexpected flags %#x.\n", flags); + + hr = IMFTransform_GetOutputStatus(copier, &flags); + ok(hr == S_OK, "Failed to get output status, hr %#x.\n", hr); + ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#x.\n", flags); + + hr = IMFTransform_ProcessInput(copier, 0, sample, 0); + ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#x.\n", hr); + + hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info); + ok(hr == S_OK, "Failed to get output info, hr %#x.\n", hr); + + hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer); + ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr); + + hr = MFCreateSample(&client_sample); + ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr); + + hr = IMFSample_AddBuffer(client_sample, media_buffer); + ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr); + IMFMediaBuffer_Release(media_buffer); + + status = 0; + memset(&buffer, 0, sizeof(buffer)); + buffer.pSample = client_sample; + hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status); + ok(hr == S_OK, "Failed to get output, hr %#x.\n", hr); + EXPECT_REF(sample, 1); + + hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status); + ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#x.\n", hr); + + /* Flushing. */ + hr = IMFTransform_ProcessInput(copier, 0, sample, 0); + ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr); + EXPECT_REF(sample, 2); + + hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0); + ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr); + EXPECT_REF(sample, 1); + + IMFSample_Release(sample); + IMFSample_Release(client_sample); + + IMFMediaType_Release(mediatype); + IMFTransform_Release(copier); +} + START_TEST(mf) { test_topology(); @@ -2768,4 +3038,5 @@ START_TEST(mf) test_MFCreateSimpleTypeHandler(); test_MFGetSupportedMimeTypes(); test_MFGetSupportedSchemes(); + test_sample_copier(); } diff --git a/include/mfidl.idl b/include/mfidl.idl index fc9173864a..cf04ec17ce 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -591,6 +591,7 @@ cpp_quote("HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock cpp_quote("HRESULT WINAPI MFCreatePresentationDescriptor(DWORD count, IMFStreamDescriptor **descriptors,") cpp_quote(" IMFPresentationDescriptor **presentation_desc);") cpp_quote("HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler);") +cpp_quote("HRESULT WINAPI MFCreateSampleCopierMFT(IMFTransform **transform);") cpp_quote("HRESULT WINAPI MFCreateSampleGrabberSinkActivate(IMFMediaType *media_type,") cpp_quote(" IMFSampleGrabberSinkCallback *callback, IMFActivate **activate);") cpp_quote("HRESULT WINAPI MFCreateSequencerSource(IUnknown *reserved, IMFSequencerSource **seq_source);" )
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66767
Your paranoid android.
=== debiant (32 bit report) ===
mf: mf: Timeout
That's strange. I don't immediately see what could trigger loader critsection deadlock at this point, half way through tests. Other run with different locale works fine too. I don't know how to use these results productively, as it never crashed like that for me. Crashes we have on tests page are also different and related to some queue shutdown issue most likely.
On Mon, 9 Mar 2020, Nikolay Sivov wrote:
That's strange. I don't immediately see what could trigger loader critsection deadlock at this point, half way through tests. Other run with different locale works fine too. I don't know how to use these results productively, as it never crashed like that for me. Crashes we have on tests page are also different and related to some queue shutdown issue most likely.
It may not be much comfort but I've seen this type of critical section timeout in WineTest runs before:
https://bugs.winehq.org/show_bug.cgi?id=48112
For instance more recently in this debiant 32 bit French run:
https://testbot.winehq.org/JobDetails.pl?Key=66562#k102
023c:err:ntdll:RtlpWaitForCriticalSection section 0x7e77ad00 "../../../wine/dlls/user32/user_main.c: user_section" wait timed out in thread 023c, blocked by 0279, retrying (60 sec) 0279:err:ntdll:RtlpWaitForCriticalSection section 0x7bd2d1e0 "../../../wine/dlls/ntdll/loader.c: loader_section" wait timed out in thread 0279, blocked by 023c, retrying (60 sec) 023c:err:ntdll:RtlpWaitForCriticalSection section 0x7e77ad00 "../../../wine/dlls/user32/user_main.c: user_section" wait timed out in thread 023c, blocked by 0279, retrying (60 sec) 0279:err:ntdll:RtlpWaitForCriticalSection section 0x7bd2d1e0 "../../../wine/dlls/ntdll/loader.c: loader_section" wait timed out in thread 0279, blocked by 023c, retrying (60 sec)
These look very much like the timeouts that happened for your patch. I don't think this is related to the locale. It seems rather random:
Timed out? (deb10)(deb10) 66562 66468 66386 66270 66145 win32 n n n n n fr_FR Y n Y n Y ja_JP Y Y Y n n zh_CN n n n Y n wow32 Y n n n n wow64 n n n n n
The same errors also happen on cw-gtx560 so they're not the result of some QEmu bug.
These critical section timeouts are also hard to notice in the WineTest runs (e.g. on test.winehq.org) since they don't prevent WineTest from completing; and the additional timeouts, if any, are lost in the middle of the other failures. The only way to really notice them is to check the Wine traces.
If anyone figures out what's up with those that would be great.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/mediatype.c | 32 ++++++++++++++++++++++++++------ dlls/mfplat/mfplat.spec | 2 +- dlls/mfplat/tests/mfplat.c | 14 ++++++++++++++ include/mfapi.h | 1 + 4 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 69b302ca89..6b67f5b33c 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -1737,10 +1737,7 @@ static int __cdecl uncompressed_video_format_compare(const void *a, const void * return memcmp(guid, format->subtype, sizeof(*guid)); }
-/*********************************************************************** - * MFCalculateImageSize (mfplat.@) - */ -HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height, UINT32 *size) +static HRESULT mf_get_image_size(REFGUID subtype, unsigned int width, unsigned int height, unsigned int *size) { static const struct uncompressed_video_format video_formats[] = { @@ -1755,8 +1752,6 @@ HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height }; struct uncompressed_video_format *format;
- TRACE("%s, %u, %u, %p.\n", debugstr_mf_guid(subtype), width, height, size); - format = bsearch(subtype, video_formats, ARRAY_SIZE(video_formats), sizeof(*video_formats), uncompressed_video_format_compare); if (format) @@ -1771,6 +1766,31 @@ HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height return format ? S_OK : E_INVALIDARG; }
+/*********************************************************************** + * MFCalculateImageSize (mfplat.@) + */ +HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height, UINT32 *size) +{ + TRACE("%s, %u, %u, %p.\n", debugstr_mf_guid(subtype), width, height, size); + + return mf_get_image_size(subtype, width, height, size); +} + +/*********************************************************************** + * MFGetPlaneSize (mfplat.@) + */ +HRESULT WINAPI MFGetPlaneSize(DWORD format, DWORD width, DWORD height, DWORD *size) +{ + GUID subtype; + + TRACE("%#x, %u, %u, %p.\n", format, width, height, size); + + memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype)); + subtype.Data1 = format; + + return mf_get_image_size(&subtype, width, height, size); +} + /*********************************************************************** * MFCompareFullToPartialMediaType (mfplat.@) */ diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 7e3bd4571c..1e11a1fc2a 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -96,7 +96,7 @@ @ stub MFGetConfigurationString @ stub MFGetMFTMerit @ stub MFGetNumericNameFromSockaddr -@ stub MFGetPlaneSize +@ stdcall MFGetPlaneSize(long long long ptr) @ stub MFGetPlatform @ stdcall MFGetPluginControl(ptr) @ stub MFGetPrivateWorkqueues diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index a93bbfe7f1..36fe9dc831 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -91,6 +91,7 @@ static HRESULT (WINAPI *pMFTUnregisterLocalByCLSID)(CLSID clsid); static HRESULT (WINAPI *pMFAllocateWorkQueueEx)(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue); static HRESULT (WINAPI *pMFTEnumEx)(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type, const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count); +static HRESULT (WINAPI *pMFGetPlaneSize)(DWORD format, DWORD width, DWORD height, DWORD *size);
static const WCHAR fileschemeW[] = L"file://";
@@ -662,6 +663,7 @@ static void init_functions(void) X(MFCreateSourceResolver); X(MFCreateMFByteStreamOnStream); X(MFCreateTransformActivate); + X(MFGetPlaneSize); X(MFHeapAlloc); X(MFHeapFree); X(MFPutWaitingWorkItem); @@ -3184,6 +3186,9 @@ static void test_MFCalculateImageSize(void) UINT32 size; HRESULT hr;
+ if (!pMFGetPlaneSize) + win_skip("MFGetPlaneSize() is not available.\n"); + size = 1; hr = MFCalculateImageSize(&IID_IUnknown, 1, 1, &size); ok(hr == E_INVALIDARG || broken(hr == S_OK) /* Vista */, "Unexpected hr %#x.\n", hr); @@ -3200,6 +3205,15 @@ static void test_MFCalculateImageSize(void) ok(hr == S_OK || (is_broken && hr == E_INVALIDARG), "%u: failed to calculate image size, hr %#x.\n", i, hr); ok(size == image_size_tests[i].size, "%u: unexpected image size %u, expected %u.\n", i, size, image_size_tests[i].size); + + if (pMFGetPlaneSize) + { + hr = pMFGetPlaneSize(image_size_tests[i].subtype->Data1, image_size_tests[i].width, image_size_tests[i].height, + &size); + ok(hr == S_OK, "%u: failed to get plane size, hr %#x.\n", i, hr); + ok(size == image_size_tests[i].size, "%u: unexpected plane size %u, expected %u.\n", i, size, + image_size_tests[i].size); + } } }
diff --git a/include/mfapi.h b/include/mfapi.h index 6636057daa..38577cfe62 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -421,6 +421,7 @@ void * WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllo void WINAPI MFHeapFree(void *ptr); HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size); HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size); +HRESULT WINAPI MFGetPlaneSize(DWORD format, DWORD width, DWORD height, DWORD *size); HRESULT WINAPI MFGetTimerPeriodicity(DWORD *periodicity); HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type, MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes,
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66768
Your paranoid android.
=== w1064v1809_zh_CN (32 bit report) ===
mfplat: mfplat.c:2587: Test failed: Unexpected return value 0x102. mfplat.c:1938: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:1941: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:1944: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. mfplat.c:1947: Test failed: Unexpected result, hr 0xc00d3e85. 19a0:mfplat: unhandled exception c0000005 at 00401AFB